C数组和指针的区别

看《C专家编程》总结的的。
首先是个经典的例子:
一个文件定义:
char a[4];
另一个文件声明:
extern char* a;
或者
extern char a[];
这两种声明会有什么后果?编译器是怎样的处理?
下面说明。
[size=large][b]一.声明和定义的概念[/b][/size]
一个变量和函数,定义只能有一次,但是声明却可以多次。
定义:确定对象的类型并分配了内存。
声明:描述了对象的类型,用于指代其他地方定义的对象。
[b][size=large]二.数组和指针编译器的处理方式[/size][/b]
[b]1.首先明白左值和右值[/b]
X = Y;
在这个情况下:
符号X的含义是X所代表的地址,这被称为左值。[color=red]在编译时可以[/color]。
符号Y的含义是Y所代表的地址的内容。这被称为右值。[color=red]右值在运行时候才知道[/color]
数组名是不可修改的左值。
[b]2.数组和指针的不同访问方式[/b]
编译器为每个变量分配一个地址。这个地址在编译时候可知,而且运行时候一直保存这个地址。而保存在变量中的值只有在运行才知道。
这里的关键是:
每个符号的地址,在编译时可知。编译器需要一个地址(有时候还需要加上偏移量)的时候,它直接操作。
而指针必须在运行时刻,先取得指针里的地址,然后才能解引用,比数组多了一个取址操作。
例子:
char a[4]="abc";
c= a[i];
数组:
编译器符号表具有一个地址:9980(数组的起始地址)
运行时刻:
步骤1:取i的值,将它与编译器所保存的地址9980相加
步骤2:取地址(9980+i)的内容。

[img]http://dl.iteye.com/upload/attachment/567374/50f22797-0a8e-3843-bdcd-4ed45c36af3c.jpg[/img]

指针:
声明为:
extern char *p;
这将告诉编译器p是个指针,其所指的内容是个字符,为了取得这个字符,需要比数组多一个步骤。
char *p =a;
c= p[i];需要三步
运行时刻:
编译器符号表有一个符号p,它的地址位4624
步骤1.取地址4624的内容 也就是 9980
步骤2.5081内容加上偏移量i形成一个新的地址
步骤3.取步骤2中形成的地址的内容

[img]http://dl.iteye.com/upload/attachment/567372/7c51b99a-f57d-33be-93eb-559cc6c976ca.jpg[/img]

[size=large][b]三.结论[/b][/size]
开头的那个例子
如果一个数组
char a[4];
被声明为:
extern char * a;

c= a[i]
运行时刻:
1.取符号表a的地址所指向的内容(数组的第一个元素)
2.将第一个步骤的数据加上偏移量形成一个新的地址。
3.访问这个地址的内容

[img]http://dl.iteye.com/upload/attachment/567388/ef16ce60-8412-3671-ad09-cb522cf8de69.jpg[/img]

看到了么?!
把数组第一个元素的内容当做地址,预期未知!!
最好的结果就是程序崩溃!


由上面我们还可以知道数组声明的时候,不需要指定大小。
理由:
1.声明的时候不分配内存,不需要大小信息。
2.访问数组成员的时候,是首地址+偏移量,不需要大小。

[size=large][b]四.其他的区别[/b][/size]
1.在ANSI C中 ,初始化指针的字符串被定义为只读。
而数组是可以修改的。

你可能感兴趣的:(C,C++)