本文来源于GitChat体验课
第01课: C标准发展
C标准的四个阶段:
K&R C
ANSI C
C99
C11
K&R C 称为传统C语言,在C语言标准统一前,这个是最权威。
ANSI C:是ANSI(美国国家标准协会), 再K&R C基础上,统一了各大编译器厂商的不同标准,并做了一些扩展,也称作 C89/C90, 至此C标准统一起来。
C99: ANSI 1999年在ANSI C上做了扩展
C11, 2011年发布的最新的标准。
不同的编译器在支持C标准的同时,也做了一些其他的扩展。
比如51单片机上, Keil for C51上支持一些关键字,如data,code,bit等
GCC编译器,扩展支持零长度数组,语句表达式等。
个人观点,如果要开发跨平台的C语言程序,尽量使用C标准内的语法,而不要使用不常见的扩展语法。
第02课: 内核驱动中的指定初始化
指定初始化数组:
标准C中常见的初始化方法:
int a[10] ={1,2,3,4}; 按照顺序初始化,未覆盖到的元素都扩展赋值为0
GNU C支持C99标准。(GNU&GCC, GCC全称是 GNU C Compiler)
C99标准,支持指定初始化,比如100个数组b[100],只初始化b[10] 和b[30]
int b[100] = { [10] = 1, [30] = 2 };
数组范围初始化,如[10] 到 [30] 赋值为1, [50]到[60]赋值为2
int b[100] = { [10 ... 30] = 1, [50 ... 60] = 2 }; ... 前后必须由空格
这种范围... 在sitch-case 语句中也可以用
switch(i)
{
case 1:
printf("1\n");
break;
case 2 ... 8:
printf("%d\n",i)
break;
defalut:
break;
}
指定初始化结构体:
struct student{
char name[20];
int age;
};
struct student stu1 = {"Ben", 18};
struct student stu2 = // 指定初始化
{
.name = "will",
.age = 28 // 后面没有逗号
};
指定初始化的好处,当结构体成员顺序发生变动,如
那么第一种stu1 初始化地方就得改, 而第二种方法完全不用改.
linux内核驱动中注册,经常遇到这种用法。
struct student{
int age;
char name[20];
char number[20];
};
第03课:语句表达式 -- 构造宏定义的好帮手
语句表达式:
GNU C对C标准进行了扩展,允许一个表达式里内嵌语句,允许表达式内部使用局部变量、for循环和goto跳转语句。这样的表达式,我们称之为语句表达式。
语句表达式最外面用小括号()括起来,里面用一对大括号{}包起来的是代码块,代码块里允许内嵌各种语句。
语句表达式内使用for循环:
int main()
{
int sum = 0;
sum =
({
int s = 0;
for( int i = 0; i < 10; i++ )
{
s = s + i;
}
s;
});
printf("sum = %d\n",sum);
return 0;
}
编译方法:gcc -o test test.c -std=gnu99 -Wall
如果不加-std=gnu99 则会报错。(参考;https://blog.csdn.net/u012075739/article/details/26516007/)
语句表达式的值邓玉最后一个表达式的值,所以再for循环的后面我们要加一个 s; 如果不加这一句则sum=0。 或者你将这一行改成100; sum的值就是100,这是因为语句表达式的值总邓玉最后一个表达式的值。
语句表达式内使用goto语句:
int main()
{
int sum = 0;
sum =
({
int s = 0;
for( int i = 0; i < 10; i++ )
{
s = s + i;
}
goto here;
s;
});
printf("sum = %d\n",sum);
here:
printf("here\n");
printf("sum = %d\n",sum);
return 0;
}
此时,sum=0
写宏定义,求两个数的最大值:MAX(a,b)
一般写法:
#define MAX(a,b) ((a)>(b)?(a):(b))
如果对于自加运算和自减运算就会有问题。
比如 MAX(a++, b++)
进阶写法1:
#define MAX(a,b) ({ \
int _x = a; \
int _y = b; \
_x > _y ? _x : _y; \
})
但是该方法仅能用于int类型,对于其他类型的比较又要重新写这个宏定义。
进阶写法2:
#define MAX(type,a,b) ({ \
type _x = a; \
type _y = b; \
_x > _y ? _x : _y; \
})
将数据类型作为一个参数传进来。