定义与声明的区别:
(1)定义就是编译器创建一个对象,为这个对象分配一块内存并为其取一个名字,这个名字就是我们常说的变量名或对象名。定义需要分配内存。
(2)声明表示该变量名或对象名在其他地方已经定义过,并且该变量名或对象名已经定义过,其他地方不能在使用该名字作为变量名或对象名。同一个变量名或对象名可以在不同的地方声明多次,并且声明不分配内存。
指针与数组的定义域声明如下两种方式都是错误的:
(1)A文件: char a[10]; B文件: extern char *a;
上述内容表示A文件声明了数组a,包含10个元素;文件B声明了一个指针变量a。声明extern char *a时,编译器认为a是一个指针变量,并且在32位系统下占用4个字节。这4个字节里面保存了一个地址,该地址存放时的字符型的数据。
编译器编译程序的过程中一般都是按照文件分别进行编译的,编译器只按照声明中声明的类型来处理。那么在A文件的编译过程中数组a的内存大小为10字节,而B文件编译过程中认为a内存大小为4字节。
假设数组a的首地址为0x0012ff44,存放了A(0x41)、B(0x42)、C(0x43)、D(0x44)等得ASCII值。在B文件中编译器认为a是一个指针变量,占用4个字节。由于编译器会将指针变量中存放的数据当做地址进行处理,那么编译器在编译B文件的时候读出a的值为0x41424344(不考虑大小端模式),在B文件中进行a的相关操作时进行去访问地址0x41424344中的内容,该地址的内容有可能不存在,即使存在得到的结果也不是我们想要得到的结果。
(2)A文件: char *p="abcde"; B文件: extern char p[ ];
在文件A中,编译器为p分配4个字节的空间,p中保存了字符串首字符的首地址,该字符串存放于静态存储区,内容不可更改。
在文件B中,编译器认为p是一个数组,其大小为4个字节,数组内保存的尾char型数据。
假设A文件中字符串首字符的首地址为0x0012ff44,在不考虑大小端模式的情况下认为p中内容为0x00 0x12 0xff 0x44。B文件中操作p时,编译器会将p当做数组来进行操作,认为品种包含4个元素,并且会按照char型数据访问或者修p[0]、p[1]、p[2]、p[3]中的值,如果进行了修改则A文件中访问字符串时将会获取错误的字符串首元素的首地址,造成访问数据失败或者访问结果错误。
综上所述,在进行数组与指针的定义与声明时切记:定义为数组,声明为数组;定义为指针,声明为指针。