@本文纯属个人笔记,如有错误还请多加指出!
源程序的预处理,编译,汇编和链接
我目前的知识水平只知道预处理时会处理#include,将其需要包含的内容包含进来,处理#define,替换符号常量。
编译就是通过词法、语法等分析产生汇编代码,汇编是指将汇编指令转换为对应的机器代码,之后链接就是链接一些必须要的库。
三字母词
C中使用三个字母表示一个符号可能会引起一些意想不到的输出,比如??(
代表[
。
字符串
当使用字符串时,便宜器会给字符串分配空间,并返回一个地址。
字符数组只能在初始化的时候使用字符串,字符串不能给字符数组赋值。
char array[]="abc";//正确
array="abc";//错误
字符串存在于表达式时,其值为这些字符的存储地址,而不是字符本身,所以不能赋值给字符数组。但是可以赋值给一个指向字符的指针。这个指针指向字符串的存储地址。
char *str="ab";//正确
str="abc";//正确
注意,数组名和指针是有区别的,参考:
数组名和指针的区别
typedef
在定义指针变量时,比如: char* a,b,c;
其实只有a是指针变量,b和c都是字符变量。
我们可以用typedef
为数据类型定义新的名字,比如:
typedef char *pChar;
pChar a,b;
这样定义的a和b都为指针变量。
而且typedef
和#define
是不一样的,前者是为数据类型定义新的名字,而后者只是简单的文本替换。
常量
可以用关键字const
来定义常量,常量不可以被赋值,因为其值为不可变的。const
常量获得值有两种方法,第一种就是在定义的时候初始化,这之后就不能修改了。第二种是const
常量作为函数的形参,当函数调用时,const
常量参数获得实参的值。
当面对指针时,根据const
修饰的位置不一样,所限制的常量也不一样:
int const *p;//值不可变,但地址可变
int * const p;//值可变,但地址不可变
举例代码:
//公用
int num1=1;
int num2=2;
int const *p1=&num1;
*p1=3;//错误,值不可变
p1=&num2;//正确,地址可变
int * const p2=&num1;
*p2=3;//正确,值可变
p2=&num2;//错误,地址不可变
还需要主要的是,const
声明的常量只能用在变量可以使用的地方,即使它的值不能被改变。所以,const
声明的常量不能用于定义数组的大小(但是,这是ANSI的规定,用GCC等可以编译,但是会有警告)(经过尝试,现在没有警告了)。
运算符结合顺序
操作符 | 描述 | 结合性 |
---|---|---|
!,~,++, - - | 前缀自增自减 | R-L |
*,& | 间接访问和取地址 | R-L |
(类型) | 类型转换 | R-L |
sizeof | 取长度 | R-L |
= | 赋值 | R-L |
+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|= | 无 | R-L |
记住一些结合顺序还是很有必要的,如果一旦万一遇到类似这样的代码++*++p
也不至于完全不知道。 ++(前缀)
和*
都是R-L结合的,所以这条语句实际上是取p指针后面一个内存单元存储的值,然后自增。