1. gcc编译器编译的完整流程,分别有什么作用?
gcc编译器编译的完整流程有四步骤,分别是预处理、编译、汇编、链接。
gcc -E hello.c -o //使用-E选项生成.i文件
编译:gcc把预处理后的结果编译成汇编语言代码,输入的是.i,编译后生成汇编语言文件.s
gcc -S hello.i -o hello.s
汇编:编译器把编译出来的汇编语言汇编成具体的CPU上的目标代码(机械代码),输入汇编代码文件.s,输出目标代码文件.o或.obj
gcc -c hello.s -o hello.o
链接:把多个目标代码模块连接成一个大的目标代码模块。输入目标代码文件.o(与其他的目标代码文件、库文件、引导代码),汇集成一个可执行的二进制代码文件.
结构体与共用体都是构造型数据类型,它们的成员变量都可以定义为不同类型的。
共用体:共用体同一个时间只能存储和使用多个变量类型的一种,当另一个时间,变量类型被改变后,原来的变量类型和值将被舍弃。共用体的作用是同一个数据项可以使用多种格式,可以节省空间。
3. static、const、volatile关键字有什么作用?
(1)修饰全局变量:变量只在本模块内可见,在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件名变量的冲突,而且不会误使用。
(2)修饰局部变量:变量在全局数据区分配内存空间,编译器自动对其初始化,其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束。
(3)修饰函数:函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数,静态函数只能在声明它的文件中可见,其他文件不能引用该函数,不同的文件可以使用相同名字的静态函数,互不影响。
(1)C编译器中,被const修饰的变量是只读变量,本质还是变量,有人称其为常变量,和普通变量的区别在于常变量不能用于左值,其余的用法和普通变量一样。
(2)C++编译器中,被const修饰的变量,变量名和初始值会直接放在符号表中,当使用变量名的时候直接从符号表中读取其值。相较于C编译器,在C++编译器中const修饰的变量更像是常量.
volatile关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据,而且读取的数据立刻被保存。
应用:当两个线程都要用到某一个变量且该变量的值会被改变中,用volatile声明,该关键字的作用就是防止优化编译器把变量从内存装入CPU寄存器中。
赋初值,也就是初始化,只能在定义的时候操作,形式为:
给变量赋初值,也叫作初始化,只能用=,而赋值语句除了=,还包括复合赋值语句,如+=、-=等,自加,自减也可以算赋值语句.
(2)用引用头文件的方式,可以在不用的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时链接不会出错。
(1)处理的时期:#define 是在编译的预处理阶段展开,而const是在编译、运行的时候起作用。
(2)#define 只是简单的字符串替换,没有类型检查。而const有对应的数据类型,是要进行判断,可以避免一些低级的错误。
(3)就存储方式而言:#define 宏在定义时不会分配内存,#define 只是进行展开,有多少地方使用,就替换多少次,它定义的宏变量在内存中有若干个备份;const 常量在定义时会在内存中分配(可以是堆中也可以栈中),const定义的只读变量在程序运行过程中只有一份备份。
const变量有数据类型,而宏常量没有数据类型,编译器可以对前者进行类型安全检查,而后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
有些集成化的调式工具可以对const常量进行测试,但不能宏常量进行测试。
指针与数组是两个完全不同的概念,当用指针表示数组时,二者都有下标表示法和*号表示法,数组名是一数组的首地址,是常量,指针变量可以指向数组,是变量。
C语言形参中数组实际上就是指针变量。不论其形式如何,它与函数内定义的数组名是不同的。其中的int a[10] 等价于,int *a;可以进行指针的各种运算,包括赋值运算,但是int b[10]就是数组名。
形参是实参的一份拷贝,当改变形参的时候不会影响到实参的值,在址传递过程中,形参虽然是实参的一份拷贝,但由于拷贝的地址,形参具有实参的能力,并且建立联系,所以修改形参,会影响到实参。
形式参数:在定义函数时,函数名后面括号中的变量名为“形式参数”。在函数调用之前,传递给函数的值将复制到这些形式参数中。
实际参数:在调用一个函数时,也就是真正使用一个函数时,函数名后面括号中的参数是“实际参数”,函数的调用者提供给函数的参数成为实际参数,实际参数是表达式计算的结果,并且被复制给函数的形式参数。
(1)数组是保存在一片连续内存单元中的,而数组名就是这片连续内存单元的首地址,内存单元的地址就是指针,因此数组名也是一个指针,数组是由多个数组元素组成,元素按其数组类型的不同,所续内存的大小也不同。
(2)一个数组的元素的首地址就是其所占连续内存单元的首地址,指针变量既可以指向一个数组,也可以指向一个数组元素。
(4)将数组名或数组的第一个元素的地址赋给指针,指针就指向一个数组。
(5)如果想使指针变量指向第i个元素,就可以把i元素首地址赋给它。