C 语言

来源:互联网 发布:安卓手机变电脑软件 编辑:程序博客网 时间:2024/06/04 00:21

1,auto:是C语言中的局部变量的默认属性;编译器默认所有的局部变量都是auto的;

2,static:关键字指明:变量的静态属性,同时具有作用域限定符的意义;static修饰的局部变量存储爱程序静态区,另一个意义是:文件作用域标识符;static声明的全局变量作用域只是声明的文件中,作用域只是声明在文件中。

3,register:关键字指明将变量存储在寄存器中,register只是请求寄存器变量,但不一定请求成功。register变量必须是cpu寄存器可以接受的值,不能用&运算符获取register变量的地址。

4,extern:用于声明外部定义的变量和函数;用于告诉编译器用C方式编译

5,const:在C语言中,const修饰的变量是只读的,其本质还是变量;const修饰的变量在内存中占用空间,本质上const只对编译器有用,在运行时无用。const修饰的函数参数表示在函数体内不希望改变参数的值;const修饰函数返回值表示返回值不可改变,多用于返回指针的情形。

6,volatile:可以理解为编译器警告指示字,用于告诉编译器必须每次去内存中去变量值,主要修饰可能被多个线程访问的变量;也可修饰可能被未知因数更改的变量。

7,struct:其中的每个域在内存中都独立的分配空间

8,union:只分配最大域的空间,所有的域共享这个空间。union的使用受系统大小端的影响。大端模式:左边是高地址,小端模式:左边是低地址。

9,enum是一种自定义类型,enum默认的常量是在前一个值的基础上依次加1,enum类型的变量只能取定义时的离散值

10,enum类型和define类型的区别:1)#define宏常量只是简单的进行值替换,枚举常量是真正意义上的常量;#define宏常量无法别调试,枚举常量可以被调试

#define宏常量无类型信息,枚举常量是一种特定类型的常量。

11,typedef:用于给一个已经存在的数据类型重命名。typedef并没有产生新的类型。typedef重定义的类型不能进行unsigned和signed扩展。

12,typedef:是给已有的类型取别名,#define为简单的 字符串替换,无别名的概念。

13,注释符号:编译器会在编译的过程中删除注释,但是不是简单的删除而是用空格代替;编译器认为双引号扩起来都是字符串,双斜杠也不例外。“/*.....*/”不能进行嵌套

14,接续符合转义符:C语言中的接续符(\)是指示编译器行为的利器,

#def \

ine MAX\

255   像这种情况就是接续符


15,接续符的作用:编译器会将反斜杠剔除,跟在反斜杠后面的字符自动解到前边一行中;在接续单词时,反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格。接续符适合在宏定义中使用。

16,转义字符:\n \t  \v \r等  ;也就是说反斜杠同时具有接续符和转义符的作用。当反斜杠作为接续符时可直接出现在程序中,当作为转义字符时,需要出现在字符或者字符串中。

17,单引号:单引号用来表示字符常量,双引号用来表示字符串常量。字符常量占用一个字节,字符串常量占用两个字节。字符串有结束符‘\0’;

18,符号运算:左移:将高位丢弃,低位补零。右移:低位丢弃,高位补符号位;左移n位相当于乘以2的n次方,右移n位,相当于除以2的n次方。

19,预编译:

1)处理所有 注释,以空格代替 2)将所有的 #define删除,并且展开所有的宏定义,3)处理条件编译指令#if,#ifdef ,#elif #else  #endif

4)处理#include ,展开被包含的文件, 5)保留编译器需使用的#pragma指令

20,预处理指令:gcc  -E file.c -o hello.i

21,编译指令:gcc  -S file.c -o hello.s

22,汇编指令:gcc --c file.s -o hello.o

23,宏表达式在预编译期被处理,编译器不知道宏表达式的存在,2)宏表达式用“实参”完全替换形参,不进行任何运算3)宏表达式没有任何调用开销 4)宏表达式中不能出现递归定义。

24,强大的内置宏:__FILE__  被编译的文件名,   __LINE__ :当前行号  ;__DATE__"编译时的日期     __TIME__ :编译时的时间   __STDC__  编译时是否遵循标准的c规范。

25,可以在函数中使用宏定义,可以使用而且可以在其他的子函数中调用

int f1(int a,int b){

#define MIN(a.b)   (a<b ? a:b)

return MIN(a,b);

}

int f2(int a,int b,int c){

return  MIN(MIN(a,b),c)

}

可以这样调用。

26,t条件编译的行为类似于C语言中的if else

2)条件编译是预编译指令命令,用于控制是否编译某段代码   #if   #else   #endif

27,#include的本质是将已经存在的文件内内容嵌套入当前的文件中,#include 的间接包含同样会产生嵌入文件内容的动作。#if  #else #endif 被预编译器处理,而if else语句被编译器处理,必然被编译进目标代码

28,#error:用于生成一个编译器错误信息,并停止编译 ;用法:#error  message 注:message不用双引号包围   #error编译指示字用于自定义程序员特有的编译错误消息,泪类似的#warning 用于生成编译警告,但不会停止编译。

29,#line 用于强制指定新的行号,和编译文件名,并对源程序的代码重新编译。用法;#line  number filename  注意:filename 可以省略。  #line 编译指示字的本质是重定义__LINE__ __FILE__

30,#pragma:是编译器指示字,用于指示编译器完成一些特定的动作;#pragma所定义的很多指示字是编译器和操作系统特有的;#pragma:在不同的编译器之间是不可移植 的。

预编译器将忽略它不认识的#pragma指令;两个不同的编译器可能以两种不同的方式解释同一条#pragma指令

31,message:参数在大多数的编译器中都有相似的实现,message:参数在编译时输出消息到编译器输出窗口中;message可用于代码的版本控制。message是VC特有的,gcc中将其忽略

32,cpu对内存的读取不是连续的,而是分快读取的,块的大小只能是1,2,4,8,16字节;当读取操作的数据未对齐时,则需要两次总线周期来访问内存,因此性能会大打折扣。

33,#pragma  pack:能够改变编译器的默认对齐方式。

#pragma pack(4)

struct  Test1{

char c1;

char c2;

   int 1;

};

#pragma pack()   由于对齐方式的不同,将导致这个结构体的大小不同

34,#和## 的运算符的使用解析:#运算符用于在预编译期将宏参数转换为字符串  #define CONVET(x)    #x

35,## 用于连接两个符号,   #define NAME(n)   name##n 


36,指针基础:

1)   指针之间只支持减法运算,且必须参与运算的指针类型必须相同。

2)a和&a的区别:a指数组的首个元素的地址;&a为整个数组的地址;a+1:表明是下个元素的地址;&a+1是整个数组后的下一个地址。


37,程序中的栈:栈保存一个函数调用所需的维护信息,函数参数,函数返回地址,局部变量,函数调用上下文,栈在函数返回后,就释放了,无法传递到函数外部,比如局部数组

38,堆,堆是程序中的一块巨大的空间,可以由程序自由使用,堆中的被程序申请使用的内存在程序主动释放前将一直有效,堆中的空间,要通过申请才能获得。

39,程序中的静态存储区:程序静态存储区随着程序的运行而分配空间,直到程序运行结束;在程序的编译期静态存储区的大小就已经确定;程序静态存储区主要用于保存程序中的全局变量和静态变量。与栈和堆不同,静态存储区的信息最终会保存到可执行程序中。

40,栈主要在函数运行的时候使用,堆区主要是用于内存的动态申请和归还,静态存储区用于保存全局变量和静态变量。

41,野指针:野指针通常是因为指针变量中保存的值不是合法的内存地址而造成的,野指针不是NULL指针,而是指向了不可用的内存的指针。NULL指针不容易用错,因为if语句很好判断一个指针是不是NULL..

42,在C语言中没有任何手段可以判断一个指针是不是野指针。

43,局部指针变量没有被初始化,使用已经释放过后的指针,指针所指向的变量在指针之前被销毁。

44,free指针后必须将指针赋值为NULL,防止出现野指针。

45,

原创粉丝点击