C 语言是一种面向过程的高级语言。 运行速度与汇编语言编写的代码运行速度几乎一样。C 语言的源码文件扩展名为 .c 例如 hello.c 。
概述
C 语言有三套标准分别是 C89 C99 C11,目前最常用的是 C99 标准。
C 编译器,写在源文件中的源代码需要编译,转化为机器语言,这样 CPU 可以按给定指定执行程序。最常用的免费可用的编译器是 GUN 的 gcc 编译器,适合于 C 和 C++ 编程语言。
在 Linux 上安装 gcc 可以采用如下命令:
yum -y install gcc yum -y install gcc-c++
也可以手动编译,可以参考 gcc 官网。
安装完成后执行 gcc -v 可以查看编辑器版本信息。
先写一个 hello.c 文件,代码如下
#include <stdio.h> int main() { printf("Hello, World! "); return 0; }
安装好 gcc 编译器后,在 hello.c 文件所在的目录下打开命令行,执行 gcc hello.c -o hello 然后会生成一个 hello.exe 文件(在 windows 环境下,如果不加 -o hello,那么默认会生成一个 a.exe),然后执行 hello.exe,即可看到屏幕显示 Hello World。
数据类型
C 语言中数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。C 中数据类型分为:
- 基本类型
- 整数类型 char int
- 浮点类型 float double
- 派生类型
- 指针类型 Pointer
- 数组类型 Array
- 结构类型 Struct
- 共用体类型 Union
- 函数类型 Function
- 枚举类型
- void 类型
以上为 C 中数据类型。
变量和常量
变量的定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。
变量声明向编译器保证变量以指定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能继续进一步的编译。变量声明只在编译时有它的意义,在程序连接时编辑器需要实际的变量声明。
变量的声明有两种情况:
- 一种需要建立存储空间的。例如 int a 在声明的时候就已经建立了存储空间。
- 另一种需要建立存储空间,通过使用 extern 关键字声明变量名而不定义它。例如:extern int a 其中变量 a 可以在别的文件中定义。
- 除非有 extern 关键字,否则都是变量的定义。
常量是固定值,在程序执行期间不会改变。又称字面量。常量分为整数常量、浮点常量、字符常量、字符串常量。
定义常量两种方式:
- 使用 #define 预处理器
- 使用 const 关键字
运算符和函数
运算符分为算术、关系、逻辑、位、赋值运算符等。
判断结构和循环结构和 Java 类似。
函数也和 Java 类似,只是在 Java 中称为方法。但是在函数参数上面稍有区别。
C 语言中调用函数时,有两种向函数传递参数的方法:
- 传值调用 把参数的实际值复制给函数的形式参数,修改函数内的形式参数不会影响实际参数。
- 引用调用 通过指针传递方法,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。
指针
个人认为,C 和 Java 最大的区别之一就是 C 有指针的概念。
每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。
#include <stdio.h> int main() { int var = 20; /* 实际变量的声明 */ int *ip; /* 指针变量的声明 */ ip = &var; /* 在指针变量中存储 var 的地址 */ printf("Address of var variable: %p ", &var); /* 在指针变量中存储的地址 */ printf("Address stored in ip variable: %p ", ip); /* 使用指针访问值 */ printf("Value of *ip variable: %d ", *ip); return 0; }
函数指针是指向函数的指针变量。 函数指针变量的声明 typedef int (*fun_ptr)(int, int) 。
#include <stdio.h> int max(int x, int y) { return x > y ? x : y; } int main(void) { /* p 是函数指针 */ int (*p)(int, int) = &max; // &可以省略 int a, b, c, d; printf("请输入三个数字:"); scanf("%d %d %d", &a, &b, &c); /* 与直接调用函数等价,d = max(max(a, b), c) */ d = p(p(a, b), c); printf("最大的数字是: %d ", d); return 0; }
C 语言也可以接受函数作为参数。
C 语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。
#include <stdio.h> #include <string.h> char *strlong(char *str1, char *str2) { if (strlen(str1) >= strlen(str2)) { return str1; } else { return str2; } } int main(void) { char str1[30], str2[30], *str; gets(str1); gets(str2); str = strlong(str1, str2); printf("Longer string: %s ", str); return 0; }
用指针作为函数返回值时需要注意,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针尽量不要指向这些数据。
预处理器 与头文件
预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已。它们会指示编译器在实际编译之前完成所需的预处理。可以把 C 预处理器(C Preprocessor)简写为 CPP。
头文件是拓展名为 .h 的文件名,包含了 C 函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:自己编写的头文件和编译器自带的头文件。
引用头文件的语法:
- #include <file> 引用系统头文件
- #include "file" 引用用户头文件
编写预处理器放在头文件中,可被多个文件引用。
错误处理
C 语言不提供对错误处理的直接支持,但是作为一种系统编程语言,它以返回值的形式允许您访问底层数据。在发生错误时,大多数的 C 或 UNIX 函数调用返回 1 或 NULL,同时会设置一个错误代码 errno,该错误代码是全局变量,表示函数调用期间发生了错误。可以在 errno.h 头文件中找到各种各样的错误代码。