<C专家编程>中有一示例,文件1中是p的声明,文件2中是p的定义,大致如下:
文件1(.h)
extern char p[]; (第一种写法,正确)
extern char* p; (第二种写法,错误)
文件2(.cpp)
char p[10];
如调用p[i],则第二种写法程序会崩溃.你可能会认为数组名就是指针,为什么会崩溃呢?
<C专家编程>有下面一段解释:
p在这里被声明为extern char* p,而它原来的定义却是char p[10].这种情况,当用p[i]这种形式提取这个声明的内容时,实际上得到的是一个字符.但按照上面的方法,编译器却把它当成是一个指针,把ASCII字符解释成为地址显然牛头不对马嘴.如果此时程序当掉,你应该额手称庆.否则的话,它很可能会污染程序地址空间的内容,并在将来出现莫名其妙的错误.
上述解释有些不容易理解,下面我详细解释下.
第一种写法,调用p[i],编译器符号表具有一个地址x.运行时步骤1:取i值与x相加.运行时步骤2:取地址(x+i)的内容.
第二种写法,调用p[i],编译器符号表具有一个p,地址为x,运行时步骤1:取地址x的内容,即y.运行时步骤2:取得i的值,并将它与y相加.运行时步骤3:取地址(y+i)的内容.
所以,第二种写法,声明的读取方法,跟实际p的定义有差别.将文件1,p[10]中的字符又解释成指针,假设为m,然后使用m的内容,导致程序崩溃.