锁定老帖子 主题:指针与数组的异同
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-05-18
1 首先,数组名不能当作赋值对象,比如下面的代码: char *s="abc"; char *s1="bcd"; s1=s; printf("%c\n",s1[0]);可以正常运行,如果把 这边的指针变为数组就会出错。 2 下面阐述一下,指针和数组各自是如何访问的: char s[]="abc"; c=s[i]; 编译器符号表有一个符号 s 地址为 1234,然后首先取i的值,把i和1234相加,然后取出(i+1234)的内容付给c. char *s="abc"; c=s[i]; 编译器符号表有一个符号s,他的地址为1234,然后取地址1234的内容,就是'5678',然后把i和5678相加,然后取出(i+5678)的内容付给c. 大家可以看下下面的这个程序: #include <stdio.h> void main() { char *s="abc"; char s2[]="789"; printf("%d\n",&s); printf("%d\n",&s[0]); printf("%d\n",&s2); printf("%d\n",&s2[0]); } 呵呵,s和s[0] 的地址竟然不一样。 3 定义指针时编译器并不为指针所指向的内容分配空间,它只分配指针本身的空间,除非在声明的同时付给指针一个字符串常量初始化。比如: char *s="abc"; 可是只有对字符串常量才是如此,其他的类型都会出错。 4 数组和指针的相同点。 。表达式中的数组名(不同于声明)被编译器当做一个指向数组第一个元素的指针。 。下标总是和指针偏移量相同,a[i]总是被编译器改写成*(a+i)这种形式来访问。(比如:a[6]和6[a]是一样的) 。在函数参数的声明中,数组名被编译器当做一个指向数组第一个元素的指针 可以看下下面的代码的输出。 #include <stdio.h> void f(char s[]); void g(char *s); char s2[4]="789"; void main() { printf("%d\n",&s2); printf("%d\n",&(s2[0])); f(s2); g(s2); } void f(char s[4]) { printf("%d\n",&s); printf("%d\n",&(s[0])); } void g(char *s) { printf("%d\n",&s); printf("%d\n",&s[0]); } 为什么c要做成这种呢,其实很简单,就是在c中调用函数的时候会把实参进行拷贝,而如果实参是数组的话,拷贝的开销太大,所以不如指针方便. 呵呵,这边多维数组没有涉及到,不过多维数组只要紧记不过是数组的数组罢了. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-05-18
hurricane1026 写道 s和s[0]竟然不同,为什么呢? 因为指针的访问和数组是不一样的,你可以看下我上面的那个解释。
char s[]="abc"; c=s[i]; 编译器符号表有一个符号 s 地址为 1234,然后首先取i的值,把i和1234相加,然后取出(i+1234)的内容付给c. |
|
返回顶楼 | |
发表时间:2007-05-18
int ,double也是不同的。
#include <stdio.h> void main() { int s[]={1,2,3}; int *d=s; printf("%d\n",&d); printf("%d\n",&d[0]); } |
|
返回顶楼 | |
发表时间:2007-05-18
只要是数组都是相同的,因为指针的话你需要先取出指针的地址然后再从这个地址取出内容(也就是指针所指的数组的第一个元素的地址),然后再取出这个地址的内容.
|
|
返回顶楼 | |
发表时间:2007-05-18
hurricane1026 写道 s和s[0]竟然不同,为什么呢?
写程序测试了一下,对于char[]确实是这样,但是对于int[],double[]都是相同的。simon测试了么? 这个是我用gcc编译运行后的结果 2280676 4202496 2280672 2280672 貌似这个char *s只在栈里分配一个指针的空间,指向实际的字符串地址(这个字符串放在哪里的? ),所以s和&s[0]的地址是不同的 而char[]是在栈里分配一个字符串,所以&s2[0]和s2的地址是同一个。 在那个程序后面加几行: printf("%d\n",&s2[1]); printf("%d\n",&s2[2]); printf("%d\n",&s2[3]); 就能观察到这个字符串的在栈中的地址是在往下增长的: 2280676 4202496 2280672 2280672 2280673 2280674 2280675 但是好像不是不是往下增长一个sizeof(char)而是一个sizeof(int),可能是因为优化的原因,具体就不清楚了 |
|
返回顶楼 | |
发表时间:2007-05-18
呵呵,增加1 难道增加的不是 sizeof(char)吗? 你可以试试 int指针,看看他是增加多少.
|
|
返回顶楼 | |
发表时间:2007-05-18
simohayha 写道 呵呵,增加1 难道增加的不是 sizeof(char)吗? 你可以试试 int指针,看看他是增加多少.
靠,快下班脑子坏了,其实看看上面s到s2的增长就能看出来,确实是增长了sizeof(char),丢人了…… |
|
返回顶楼 | |
发表时间:2007-05-18
hurricane1026 写道 s和s[0]竟然不同,为什么呢?
s 和 s[0] 类型不同 char *s="abc"; &s --> char ** &s[0] --> char * 对于普通数组,s 应该和 &s[0] 相同 |
|
返回顶楼 | |
发表时间:2007-05-18
xin_wang 写道 hurricane1026 写道 s和s[0]竟然不同,为什么呢?
写程序测试了一下,对于char[]确实是这样,但是对于int[],double[]都是相同的。simon测试了么? 这个是我用gcc编译运行后的结果 2280676 4202496 2280672 2280672 貌似这个char *s只在栈里分配一个指针的空间,指向实际的字符串地址(这个字符串放在哪里的? ),所以s和&s[0]的地址是不同的 char* s="xxxxxx"; s的实际地址指向常量区的值为xxxxxx的地址,也就是说,s是一个字符串常量 看这段: #include <stdio.h> #include <stdlib.h> char* s1(); char* s2(); int main() { printf("%s",s1()); printf("%s",s2()); } char* s1() { char *a="aaaaa"; return a; } char* s2() { char a[]="bbbbbbb"; printf("%s",a); return a; } s1的方法返回的是正确的字符串,s2就不敢保证了,因为他的char a[]="bbbbbbb";只是在当前栈中,a返回的是个可能无效的地址(我是说可能,因为编译器可能那个时候没有覆盖这段内存) |
|
返回顶楼 | |
发表时间:2007-05-18
看这段:
#include <stdio.h> #include <stdlib.h> char* s1(); char* s2(); int main() { printf("%s",s1()); printf("%s",s2()); } char* s1() { char *a="aaaaa"; return a; } char* s2() { char a[]="bbbbbbb"; printf("%s",a); return a; } s1返回的是正确的字符串,因为s1引用的是不变的常量区;s2则是引用的栈的内存,所以s2有可能出现不正确的结果(在我的gcc上,是乱码),但是在s2内部没有问题,因为在s2内部,指向栈的引用是有效的 |
|
返回顶楼 | |