c 语言基础语法1
C 语言程序结构
1. 示例程序
我们先看一个最简单的可以执行的 C 语言的程序:
执行这个程序,就会在我们的命令行中输出如下内容:
Hello World!
2. 结构解析
2.1 main 函数
在每个 C 语言程序中都需要包含一个 main 函数。这是程序的主体,每个可以单独执行的 C 语言程序都要有一个 mian 函数作为程序的入口程序,如同每个建筑物都会有一个主要的出入口一样。
这个函数由函数名后的一对圆括号,以及在圆括号后面的一对大括号,和包含在大括号内的一组程序代码构成。这个圆括号中可以放置需要在程序启动时传入 main 函数的参数。可以是一个,或者多个参数。而在这之后的大括号中的部分,就是这个程序的主体部分。里面是可以执行的程序语句或者注释等相关内容。
Tips:按照 C 语言的国际标准,这个函数是有一个返回值的,而且类型只能是 int 类型。但是在一些旧的书籍中,会有 void 的返回类型写法。这个写法在我目前遇到的编译器中不会有问题。但是切记,这不是 C 语言标准写法,在某些新的编译器中会产生错误。程序是一个需要极其遵守规则的领域,小聪明总会付出沉重的代价。
2.2 # include 指令
为了调用标准 IO 库中提供的 printf 这个函数。我们这里使用了 # include <stdio.h> ,这个语句代表了我们要在程序中使用 STDIO 库中提供的函数,我们也会把 stdio.h 这样的文件称之为头文件。
头文件里面主要包含着函数的声明。这就可以方便我们重复使用别人已经实现了的程序,能使用别人的,一般都不要自己来实现,这叫做不要自己来发明轮子。更深入的讲一点,其实这个是一个预处理指令。这个指令会在程序编译时,指引编译器找到我们所需要引用的内容。
2.3 int x,y,z;
这一句是声明了 3 个整数型的变量。在 C 语言中,变量要先通过声明类型,然后才能使用。这一点和某些编程语言有点不太一样。不同的变量类型在 C 语言中会对应不同的内存分配大小。
2.4 printf 函数
除了上面所说的部分外,其余的部分是程序语句。
printf 函数是向标准终端中输出格式化的文本。
return 函数是在程序执行到此结束程序并返回其所携带的参数数值。
语句一般是功能函数与分支结构的组合。
程序会根据条件的变化来执行相应的操作,最终计算出我们需要的结果。
而所谓 bug 其实就是我们预想的结果和程序最终呈现给我们的结果不一致而已。
C 语言中的注释
编程语言的注释是为了程序员维护代码而出现的。注释内容其本身并不参与程序的编译与执行,注释的出现只是为了记录一些文本信息而出现的。
在自由软件出现后,注释的更为重要的功能就是声明软件的授权使用协议。这在除我国在外的,其他很多国家具有法律效力。
1. C 语言的注释标准
C 语言的注释目前有两种:
- 多行注释(经典式注释)
- 单行注释(C++ 式注释)
1.1 多行注释
以 /* 注释内容 */ 形式出现的注释。注释可以写在一行,也可以跨越多行。只要在注释的开始使用 /* 标明,在注释全部写完后用 */ 结束就可以了。被这两组符号包围的部分就是注释主体。
/* 注释的示范程序 可以跨越多行进行注释 */ /************************************** 为了强调可以这样标注,可以写很长的注释体。 一般自由软件会有很长的授权协议写在开头, 大家使用别人软件的时候请仔细阅读。 ***************************************/ # include <stdio.h> int main() { /* 声明变量 */ int x,y,z; return 0; /* 返回值 */ }
1.2 单行注释
但是如果不使用 IDE ,而使用键盘敲击注释内容,每次都要敲击 4 次键盘才能完成一次注释,对于一些简短的注释来说是比较麻烦的。
因此在 C++ 语言设计的时候,就出现了使用 // 来进行单行注释的方法。请注意,这里编译器只会忽略 // 后面到本行行末的部分。也就是只能注释一行。这与使用 /* */ 方式注释可以同时注释多行的方式有所不同。这种注释的方法优缺点显而易见。与上面的传统方式优势互补。
Tips:需要特别注意的是,对于几十年前的老旧的编译器,这种注释方式会引起错误。当然,最近十年的编译器已经可以支持这种新的注释标准了。
# include <stdio.h> int main() { // 声明变量 int x,y,z; return 0; // 返回值 }
将两种注释方式混合使用的例子。
/* 使用第一种方式注释 */ # include <stdio.h> int main() { // 使用第二种方式注释 int x,y,z; return 0; }
C 语言中的变量
在讲解变量之前,我们先来看一段代码:
int x; int y=0; char z='A'; x=6;
在上面这段代码中出现的 x、y、z 都是一个 C 变量。
变量是编程语言中不可或缺的组成部分。它承载这存贮数据以及计算结果等等功能,顾名思义变量就是可以再计算执行过程中变化的量。这节课我们来学习下到底什么是变量。
1. 什么是变量?
变量是程序用来保存计算结果的存储单元,为了方便访问这块存储单元,我们给这块存储单元命名,该名称即为变量名,在程序中通过变量名来访问保存计算结果的存储单元。
在下图中,在内存中有一块存储区域保存了计算结果 123,在程序中使用变量 X 表示这一块存储区域。
你可以简单的把变量理解为一个存储数据的盒子,我们要存储的数据平时就放在盒子中。当我们要使用数据的时候把盒子打开吧数据取出来就可以了。
2. C 语言中定义变量
在 C 语言中定义变量如下:
int x;
上面这行代码就声明了一个名为 x 的变量,这行代码分为三部分:
- int:int 表示变量存储的数据类型。数据类型的概念我们下个小节详细讲解;
- x:x 表示变量名称;
- ;:C 语言代码每一行都用分号结尾。
3. 变量命名规则
为了更方便程序的阅读,以及让程序更加的规范,给变量命名的时候不可以随意命名,需要遵守变量的命名规则:
- 变量名称可以是由字母,数字,下划线(
_)组成; - 字母可以是大写字母,也可以是小写字母;
- 单个字母可以作为变量名,但是单个数字和下划线不可以单独作为变量名;
- 当组成变量名的字符大于等于 2 个时,字母和下划线可以作为变量名第一个字符,但是数字不可以;
- 理论上变量名的长度是没有限制的,但是有的编译器超过 31 个字符就会产生错误。不过超长的字符变量名也会给编写和阅读程序带来不便。
Tips:请注意英文字母变量的大小写。在 Linux 以及 Unix 系统中,是严格区分大小写的。
int A和int a,会被认为是两个不同的变量。
实例:
int A, a, _A, c0, _ddf5, res_1;
Tips:C 语言可以一行代码声明多个变量。
上面举了几个符合规则的变量名的例子。但是合乎规则不等于是合格的变量名。具体的变量名最好与要存储的内容有一定关联,便于程序阅读。例如我的变量中要存储的是数学成绩分数,那么变量名可以叫做:
int Math_scores;
4. 变量的使用
变量的使用分为两个步骤,声明变量和为变量赋值,也叫初始化变量。
声明变量类型,初始化变量。
# include <stdio.h> int main(void) { int x,y; int z=0; x=2,y=5; z=x+y; printf("%d",z); return 0; }
# include <stdio.h> int main(void) { char abc; abc='I'; printf("%c",abc); return 0; }
C 语言中的变量类型
对于 C 语言的变量类型这里有两种说法:
一种是只包含基础的变量类型,如整数型,浮点型等;
另外一种则是在上述类型的基础上还包含了一些用户可以定义的复合的类型,如 array,structure 等等。
我们这里只介绍大家通常意义上所认识的前一种基本的 C 语言数据类型。更为复杂的这些数据组合的结构,我们会在后面单独列出。
1. 变量类型
因为 C 语言与需要编译之后才能执行,所以需要对变量指定类型后才能使用。因为 C 语言会对不同的数据类型分配不同的内存大小,这就是为什么 C 语言需要指定数据类型,而诸如 PHP, Python 这样的语言不需要指定。指定大小的好处是可以让程序处理起来更快,内存的开销更小。
变量类型列表
| 类型 | 存储长度 | 数值范围 |
|---|---|---|
| char | 1 byte | -128 to 127 |
| unsigned char | 1 byte | 0 to 255 |
| signed char | 1 byte | -128 to 127 |
| int | 4 bytes | -2,147,483,648 to 2,147,483,647 |
| unsigned int | 4 bytes | 0 to 4,294,967,295 |
| short | 2 bytes | -32,768 to 32,767 |
| unsigned short | 2 bytes | 0 to 65,535 |
| long | 8 bytes | -9223372036854775808 to 9223372036854775807 |
| unsigned long | 8 bytes | 0 to 18446744073709551615 |
对于用科学计数法表示的类型还涉及到小数可以表示的精度,也就是有效数字。请看下面的表格:
| 类型 | 存储长度 | 数值范围 | 小数点后的位数 |
|---|---|---|---|
| float | 4 byte | 1.2E-38 to 3.4E+38 | 6 |
| double | 8 byte | 2.3E-308 to 1.7E+308 | 15 |
| long double | 10 byte | 3.4E-4932 to 1.1E+4932 | 19 |
这里有一个程序可以输出你的计算机中的不同数据结构在内存中所占用的内存的位数。对于不同的硬件这个返回值是不同的。
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <float.h> int main(int argc, char** argv) { printf("CHAR_BIT : %d\n", CHAR_BIT); printf("CHAR_MAX : %d\n", CHAR_MAX); printf("CHAR_MIN : %d\n", CHAR_MIN); printf("INT_BIT : %d\n", sizeof(int)); printf("INT_MAX : %d\n", INT_MAX); printf("INT_MIN : %d\n", INT_MIN); printf("LONG_BIT : %d\n", sizeof(long)); printf("LONG_MAX : %ld\n", (long) LONG_MAX); printf("LONG_MIN : %ld\n", (long) LONG_MIN); printf("SCHAR_BIT : %d\n", sizeof(signed char)); printf("SCHAR_MAX : %d\n", SCHAR_MAX); printf("SCHAR_MIN : %d\n", SCHAR_MIN); printf("SHRT_BIT : %d\n", sizeof(short)); printf("SHRT_MAX : %d\n", SHRT_MAX); printf("SHRT_MIN : %d\n", SHRT_MIN); printf("UCHAR_BIT : %d\n", sizeof(unsigned char)); printf("UCHAR_MAX : %d\n", UCHAR_MAX); printf("UINT_MAX : %u\n", (unsigned int) UINT_MAX); printf("ULONG_BIT : %d\n", sizeof(unsigned long)); printf("ULONG_MAX : %lu\n", (unsigned long) ULONG_MAX); printf("USHRT_MAX : %d\n", (unsigned short) USHRT_MAX); printf("Storage size for float : %d \n", sizeof(float)); printf("Strage size for double : %d\n", sizeof(double)); printf("FLT_MAX : %g\n", (float) FLT_MAX); printf("FLT_MIN : %g\n", (float) FLT_MIN); printf("-FLT_MAX : %g\n", (float) -FLT_MAX); printf("-FLT_MIN : %g\n", (float) -FLT_MIN); printf("DBL_MAX : %g\n", (double) DBL_MAX); printf("DBL_MIN : %g\n", (double) DBL_MIN); printf("-DBL_MAX : %g\n", (double) -DBL_MAX); printf("Float precision value : %d\n", FLT_DIG ); printf("Double precision value : %d\n", DBL_DIG ); return 0; }
将上面的程序粘贴到文本编辑器中,然后以 test.c 文件名保存。
在终端命令行中输入
gcc test.c -o test
编译完成后
./test
来执行上面的程序。
我的树莓派4上输出的结果如下:
CHAR_BIT : 8 CHAR_MAX : 255 CHAR_MIN : 0 INT_BIT : 4 INT_MAX : 2147483647 INT_MIN : -2147483648 LONG_BIT : 4 LONG_MAX : 2147483647 LONG_MIN : -2147483648 SCHAR_BIT : 1 SCHAR_MAX : 127 SCHAR_MIN : -128 SHRT_BIT : 2 SHRT_MAX : 32767 SHRT_MIN : -32768 UCHAR_BIT : 1 UCHAR_MAX : 255 UINT_MAX : 4294967295 ULONG_BIT : 4 ULONG_MAX : 4294967295 USHRT_MAX : 65535 Storage size for float : 4 Strage size for double : 8 FLT_MAX : 3.40282e+38 FLT_MIN : 1.17549e-38 -FLT_MAX : -3.40282e+38 -FLT_MIN : -1.17549e-38 DBL_MAX : 1.79769e+308 DBL_MIN : 2.22507e-308 -DBL_MAX : -1.79769e+308 Float precision value : 6 Double precision value : 15
这台单板计算机的处理器是 arm64。
在树莓派2上的输出结果如下:
CHAR_BIT : 8 CHAR_MAX : 255 CHAR_MIN : 0 INT_BIT : 4 INT_MAX : 2147483647 INT_MIN : -2147483648 LONG_BIT : 4 LONG_MAX : 2147483647 LONG_MIN : -2147483648 SCHAR_BIT : 1 SCHAR_MAX : 127 SCHAR_MIN : -128 SHRT_BIT : 2 SHRT_MAX : 32767 SHRT_MIN : -32768 UCHAR_BIT : 1 UCHAR_MAX : 255 UINT_MAX : 4294967295 ULONG_BIT : 4 ULONG_MAX : 4294967295 USHRT_MAX : 65535 Storage size for float : 4 Strage size for double : 8 FLT_MAX : 3.40282e+38 FLT_MIN : 1.17549e-38 -FLT_MAX : -3.40282e+38 -FLT_MIN : -1.17549e-38 DBL_MAX : 1.79769e+308 DBL_MIN : 2.22507e-308 -DBL_MAX : -1.79769e+308 Float precision value : 6 Double precision value : 15
这台单板计算机的处理器是 arm32。
在我的笔记本电脑上运行的结果如下:
CHAR_BIT : 8 CHAR_MAX : 127 CHAR_MIN : -128 INT_BIT : 4 INT_MAX : 2147483647 INT_MIN : -2147483648 LONG_BIT : 8 LONG_MAX : 9223372036854775807 LONG_MIN : -9223372036854775808 SCHAR_BIT : 1 SCHAR_MAX : 127 SCHAR_MIN : -128 SHRT_BIT : 2 SHRT_MAX : 32767 SHRT_MIN : -32768 UCHAR_BIT : 1 UCHAR_MAX : 255 UINT_MAX : 4294967295 ULONG_BIT : 8 ULONG_MAX : 18446744073709551615 USHRT_MAX : 65535 Storage size for float : 4 Strage size for double : 8 FLT_MAX : 3.40282e+38 FLT_MIN : 1.17549e-38 -FLT_MAX : -3.40282e+38 -FLT_MIN : -1.17549e-38 DBL_MAX : 1.79769e+308 DBL_MIN : 2.22507e-308 -DBL_MAX : -1.79769e+308 Float precision value : 6 Double precision value : 15
这台电脑的处理器是 x86_64 架构,也就是大家在市场上买到的家用电脑的架构。
大家可以看到这里有些数值是一样的,但是有些却不同。这就是计算机硬件上的差异,大家在使用 C 语言给硬件编程的时候一定要考虑到这点影响。

浙公网安备 33010602011771号