菜鸟的成长之——C语言知识梳理

来源:互联网 发布:力劲注塑机怎么调数据 编辑:程序博客网 时间:2024/05/18 02:45

花了一段时间整理C语言知识,将一些需要注意的地方总结如下:

**关键字篇:

register—必须是一个单一的值,并且长度应小于等于整型的长度。并且rigister变可能不存放在内存中,所以不能用取地址运算符“&”来获取其地址。


static—被static修饰的变量总是存在内存的静态区,所以即便函数结束,这个静态变量的值依然存在,下次仍然可以使用。
在修饰全局变量时,作用域仅限于变量被定义的文件中,其他文件即使用extern声明也无法使用它。(除非在前面加extern*)**


sizeof—在计算变量所占的空间大小时,括号可以省略;在计算类型的大小时,括号不可省略。
例:sizeof i;(正确) sizeof int;(错误)
sizeof (i);(正确) sizeof (int);(正确)


case—case后面只能是整型或字符型的常量或常量表达式。
(switch—case语句不是匹配度高的优先匹配,而是就近匹配。)


void

(空类型):注释/限制程序
真正发挥的作用在于:1对函数返回的限定 2对函数参数的限定

void*—(空指针):可以指向任何类型的数据
空指针可以包容任何类型,但是有类型不能包容空指针

 例:    void*p1;    int*p2;    p1=p2;(√ 空指针可以包容有类型)   int*p1;   void*p2;   p1=p2;(×有类型不能包容空指针)

注1:无论在C/C++中,若函数不接受任何参数,一定指明参数为void
2:void不能代表一个真实变量(系统定义void变量,不知开辟多大的内存空间)


return—return语句不可返回指向栈内存的指针,因为该内存在结束时会被自动销毁。


**

const

**

(只读变量)—修饰常量
全局的只读变量,存放在静态区
注1:const只读变量,具有不可变性——不能用来定义数组的维数,也不能放在case之后。
2:const修饰的只读变量必须在定义的同时初始化。
3:编译器通常不为普通const只读变量分配存储空间,而是将他们保留在符号表中,使得它成为一个编译期间的值,没有了存储与读内存的操作。——节省空间,避免不必要的内存分配,提高效率。
4:修饰指针时,就近原则,——离谁近就修饰谁。
5:const可修饰函数的参数(防止参数值被函数体的意外改变)


volatile

(易变,不稳定)
当要求使用volatile声明变量时,系统会重新对它所在的内存读取数据。精确地说,当遇到此关键字声明变量时,编译器对访问该变量的代码不进行任何优化,
**从而 int *ip =…; //设备地址
*ip = 2; //第二个指令
以上程序compiler可能做优化而成:
int *ip = …;
*ip = 2; 任何的优化,从而保证程序的原意:
volatile int *ip = …;
ip = 1;*
ip = 2;
volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能重复使用放在存储器或寄存器中的备份。**



union

—主要用来压缩空间—配置一个足够大的空间以容纳最大长度的数据成员。
注:1所有的数据成员共用一个空间
2同一时间,只能存储一个数据成员
3所有的数据成员具有相同的起始地址



运算符篇:

因运算符导致表达式的优先级问题——容易出错的情况
表达式优先级常出错情况:



预处理篇

#define宏定义表达式
注:宏函数被调用时是以实参代换形参,而不是“值传达”。
涉及到运算符优先级的问题,不能忘了带括号。。。。。

1#define SQR(x)  x*xx=10+1,替换后SQR(x)为:10+1*10+1=21(≠121)——#define SQR(x) ( x)*(x)2#define  SQR(x) (x)+(x)代码为:SQR(x*SQRx)若x=5*3,替换后SQR(x)为:(5*3)+(5*3*(5*3)+(5*3)=255(≠900)——#define  SQR(x) ((x)+(x))


#pragma预处理

——设定编辑器的状态/指定编辑器完成一些特定的动作。
常用的:
eg1:#pragma message(消息文本)
当编辑器遇到这条指令时就在编译输出窗口将消息文本打印出来。
eg2:#pragma once
在头文件最开始加入,以保证头文件被编译一次。

eg3:#pragma warning
# pragma warning(disable:4996 996):不显示4996和996号警告消息。
#pragma warning(once:4385):4385号警告消息仅报告一次。
#pragma warning(error:4385):4385号警告消息作为一个错误。
#pragma warning(push):保存所有信息的现有的警告状态。
#pragma warning(push,n):保存所有信息的现有的警告状态,并且把全局警告等级设定为n。
#pragma warning(pop):向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。
#pragma comment——将一个注释记录放入一个对象文件或可执行文件中。
eg3: #pragma pack
#pragma pack(n):编译器按n个字节对齐。
#pragma pack():编译器取消自定义字节对齐方式。
#pragma pack(push):保存当前对齐方式到packing stack
——等效于#pragma pack(push,n)
#pragma pack(pop):packing stack出栈,并将对齐方式设置为出栈的对齐方式。




#运算符

 #define SQR(x)  printf("The square of x is %d\n",((x)*(x)) ;   SQR(8);  输出:The square of x is 64  (此时,字符x被当做普通文本处理,而非可替换的语言符号。)若改为: #define SQR(x)  printf("The square of#x is %d\n",((x)*(x)) ; SQR(8);  输出:The square of x is 64 (此时,字符x被当做普通文本处理,而非可替换的语言符号。)

##运算符
用于宏函数的替换部分,把两个语言符号组合成单个语言符号,

eg:#define XNAME(n) x##nXMAME(8

则会被展开成:x8

(c语言基础很差,请各位大佬不要见笑~~)

原创粉丝点击