C语言语法 即关键字的使用方法
1. 关键字介绍 如何处理01,内存意识
翻译器的目的是要把C程序翻译为一串01放于内存中,供CPU执行。而C的语法就是告诉翻译器如何翻译,所以一个优秀的C程序员,看到的只C的源代码,想到的应该是这串01应该怎么“玩”。你写出一行代码,它为你翻译为01,至于接下来这串01怎么玩,你随便(只要不越出操作系统的控制 )!
1. 关键字分类
a) 符号声明关键字 在机器中注册一个助记符
char / int / …… / float / void 告诉机器助记符关联的内存块的解释方式
struct / enum / union / typedef 定义一种新的内存块解释方式
b) 类型修饰关键字 01内存块的解释细节
short / long / unsigned / signed 只能修饰原生类型
c) 符号修饰关键字 如何获取助记符实体
* / & / [] / () / const / register / extern / volatile / static / restrict
d) 流程控制关键字
break else switch case return continue for default do if while
e) 机器信息获取关键字
sizeof / __LINE__ / __FILE__ /__STDC__ / __FUNC__ / __TIME__ / __DATE__
2. 变量符号实质 声明、定义、赋值
a) 定义一个符号name_a,翻译器会在符号表中加入一项记录 name_a 与 name_a关联的内存实体的地址,以便使用name_a时,可以得到name_a对应的 01
b) 声一个符号name_a,翻译器只会在符号表中加入name_a,但是空出 name_a关联的内存地址,以便在日后定义时填入。
c) 符号的赋值 name_a = name_b,就是将name_b关联的实体01拷贝到name_a关联的实体处。为了保证两块实体大小相同,机器要求name_a与name_b相同类型(例外之处,两个指针或者char/int这些已知转化方式的数据赋值时,只是提出警告)。
3. 类型符号的使用 struct / union / enum typedef
a) struct / union 使用现有类型组装一个新的内存块解释方式
b) enum 向机器注册数据符号,符号的关联值并不是内存址,而是符号的值。所以enum声明的符号只能表示常数int。
c) typedef 符号反射为类型符号
struct A_t m; struct A_t A A m; //两个m是等效的
int a[100]; typedef int A[100]; A a; //两个a是等效的
4. 符号修饰关键字 extern / volatile / static / * / [] / const / restrict
a) extern / volatile / static 声明符号的
b) restrict 告知机器符号关联的内存不被其它指针指向,机器不检查。
- void * memcpy(void * restrict s1, const void * restrict s2, size_t n);
- void * memove(void * s1, const void * s2, size_t n);
c) * 与 [] 的种种关系
1. 由int *a,b; a为指针符号,b为变量符号,可知*的作用是修饰符号。“真正”的变量符号为*a。a只是一个简单变量符号,它关联的内存中存储的值是“*a这个变量”关联的地址。
2. [] 声明助记符name_a,name_a的关联值就是这n个元素的内存实体的起始值,name_a的修饰为int[10]。当name_a在“=”右边时,认为是一个指针;当name_a在等号左边时认为是一个数组。
3. 数组指针的运算 &name_a + 1 等值于 (int)(&name_a)+sizeof(name_a)
注,对于数组的这种表现只能说是翻译器作出的一种特殊的解释方式,不能用简单的符号表记录机制处理。
4. 数组与指针的复杂逻辑 修饰优先级 [] 高于 *
int *a[20]; a是一个数组,数组元素是int *;
int (*a)[20]; a是一个指针,指向的是一个int [20]的数组。
d) * 与 () 的种种关系 其操作性与 [] 基本一致
- () 用来声明函数符号
- int fun(); sizeof(fun) == 1
e) const 常量符号
- int const *p const 修饰的是 变量符号 *p p所指地址中的值不变
- int *const p const 修饰的是 变量符号 p p的值不变
5. 错综的关键字修饰分析 分离类型修饰与符号修饰后按优先级分析
Ø int *a[20] 与 int (*a)[20] unsigned int *a[20]
Ø int (*const p)[20] p是一个常量,且是一个指针,指向int[20]的地址块
Ø int *p()[]; p是一个函数,返回值为int*[]
Ø int *p[](); p是一个数组,元素为int*() 返回int*函数
6. 传值调用 —— 本质是形参作为一个新符号(可能已被修饰),其值复制实参的关联值
1. 变量
int fun(int name_a)
fun (name_b); 调用时,将name_b关联的内存赋值给name_a
2. 指针
int fun(int *name_a)
fun (&name_b); 调用时,将&name_b关联的内存赋值给*name_a
3. 数组
int fun( int a[20]);
fun(b); 实际上是调用 b = a; 见上面分析,a以指针做右值
2. 机器特性
3. 语法特性1. 精度问题,浮点数计算不可结合。
2. int 长度为32位,将int转型后的指针在64位机上可能会出错。
1. 计算基于32(64位机为64)运行,加载原符号关联的内存值入寄存器,扩展/截断为机器位长。类型关键字(尤其是类型修饰关键字)价值只是告诉编译器如何进行位长处理)。
2. 数据比较操作:
1. int 之间默认以无符号比较; sint 与sint 以有符号比较
2. 短符号间比较,若存在singed符号,以有符号扩展后比较
3. 不同长度,若存在uint 以无符号比较。
3. 浮点数表示