C基础,计算机中的数以及volatile限定修饰符,指针及其注意事项,external,static,Void *

来源:互联网 发布:做淘宝月收入多少 编辑:程序博客网 时间:2024/06/05 21:05


在C语言中可以用volatile限定符修饰变量,就是告诉编译器,即使在编译时指定了优化选项,每次读这个变量仍然要老老实实从内存读取,每次写这个变量也仍然要老老实实写回内存,不能省略任何步骤。


extern关键字表示这个标识符具有ExternalLinkag


static关键字修饰一个函数声明,则表示该标识符具有Internal Linkage


指针:把一个变量所在的内存单元的地址保存在另外一个内存单元中,保存地址的这个内存单元称为指针,通过指针和间接寻址访问变量,这种指针在C语言中可以用一个指针类型的变量表示

&是取地址运算符。

全局变量只能用常量表达式初始化,如果定义int p = i;就错了,因为i不是常量表达式,然而用i的地址来初始化一个指针却没有错,因为i的地址是在编译链接时能确定的,而不需要到运行时才知道,&i是常量表达式


*号是指针间接寻址运算符。*pi表示取指针pi所指向的变量的值。

&运算符的操作数必须是左值,因为只有左值才表示一个内存单元,才会有地址,运算结果是指针类型。*运算符的操作数必须是指针类型,运算结果可以做左值。所以,如果表达式E可以做左值,*&E和E等价,如果表达式E是指针类型,&*E和E等价。

用一个指针给另一个指针赋值时要注意,两个指针必须是同一类型的。在我们的例子中,pi是int *型的,pc是char *型的,pi = pc;这样赋值就是错误的。但是可以先强制类型转换然后赋值。



现在pi指向的地址和pc一样,但是通过*pc只能访问到一个字节,而通过*pi可以访问到4个字节,后3个字节已经不属于变量c了,除非你很确定变量c的一个字节和后面3个字节组合而成的int值是有意义的,否则就不应该给pi这么赋值。因此使用指针要特别小心,很容易将指针指向错误的地址,访问这样的地址可能导致段错误,可能读到无意义的值,也可能意外改写了某些数据,使得程序在随后的运行中出错。


有一种情况需要特别注意,定义一个指针类型的局部变量而没有初始化。在堆栈上分配的变量初始值是不确定的,也就是说指针p所指向的内存地址是不确定的,后面用*p访问不确定的地址就会导致不确定的后果,如果导致段错误还比较容易改正,如果意外改写了数据而导致随后的运行中出错,就很难找到错误原因了。像这种指向不确定地址的指针称为“野指针”(Unbound Pointer),为避免出现野指针,在定义指针变量时就应该给它明确的初值,或者把它初始化为NULL。

Null:就是把地址0转换成指针类型,称为空指针,它的特殊之处在于,操作系统不会把任何数据保存在地址0及其附近,也不会把地址0~0xfff的页面映射到物理内存,所以任何对地址0的访问都会立刻导致段错误。*p = 0;会导致段错误,就像放在眼前的炸弹一样很容易找到,相比之下,野指针的错误就像埋下地雷一样,更难发现和排除,这次走过去没事,下次走过去就有事。


Void * 类型指针:在编程时经常需要一种通用指针,可以转换为任意其它类型的指针,任意其它类型的指针也可以转换为通用指针,最初C语言没有void *类型,就把char*当通用指针,需要转换时就用类型转换运算符(),ANSI在将C语言标准化时引入了void *类型,void *指针与其它类型的指针之间可以隐式转换,而不必用类型转换运算符。注意,只能定义void *指针,而不能定义void型的变量,因为void *指针和别的指针一样都占4个字节,而如果定义void型变量(也就是类型暂时不确定的变量),编译器不知道该分配几个字节给变量。同样道理,void *指针不能直接Dereference,而必须先转换成别的类型的指针再做Dereference


0 0
原创粉丝点击