数组名a和&a的异同
热5已有 970 次阅读 2009-12-31 13:14flyreally原创,希望对新手能有所帮助。
写这篇文章纯粹是因为WJ的那篇关于C语言考察题目,本人比较菜,第一次看到如下代码
char a[] = "abcd";
printf("%c, %c\n", *(a + 1), *(&a + 1));
看完之后觉得输出结果应该是b, b,但实际却不是,纳闷了好久,一直搞不明白,最近看书有点想法,总算搞明白了,说说自己的想法吧。
我先回顾几个概念:
1.指针:指针就是内存单元的地址,是一个常量。
2.指针变量:用于存储指针的变量,是一个变量。
3.数组名:数组名是一种特殊的指针(数组名和指针的异同请看《C专家编程》),代表的该数组在内存中的起始位置。
我们再看看指针可以有哪些加减运算
1.指针的加法运算:两个指针变量相加无意义;指针跟int、long、char型变量或整形常量相加,代表从当前指针的偏移量,具体偏移多少,由指针所指向的数据类型决定。
2.指针的减法运算:两个指针变量相减,相当于求这两个指针的偏移量,大多用于指向同一数组的两个指针变量的运算。
我们还需要知道不同数据类型在内存中所占用的空间,以32位平台为例说明。
int占4个字节,指针变量占4个字节,char占一个字节,其他的就不列举了。指针变量为什么占4个字节呢,因为我们的系统是32位,也就是系统的寻址能力是32位,以XP来说,XP的寻址能力就是2^32=4GB,每个内存单元的地址就是32位,所以就是4个字节,当然,这是微机原理中的内容了 。
了解了这些,我们言归正传。
我们都知道,数组名是一个特殊的指针,代表的是该数组在内存单元中的首地址,而且《C专家编程》中提到,数组名在表达式中跟指针等价,那么为什么a + 1和&a + 1的指向不同呢?
我在前面提到,指针和int、long、char型变量或整形常量相加减的时候,就是求相对于当前指针的偏移量,而偏移量具体是多少,由该指针所指向的数据类型决定。比如说:
int *p = 1000; //此处仅为说明异同而如此赋值
char *q = 2000;
p + 1跟q + 1的结果相比,偏移量是截然不同的,p + 1指向1004(32位平台),而q + 1指向2001,这就说明了,偏移量的多少,完全由指针所指向的数据类型决定,偏移量就等于对指针所指向的数据类型求sizeof。
现在我们就可以明白为什么对于数组a,a + 1的指向的地址跟&a + 1不同了,在表达式中,数组名等同于指针,所以数组名a就相当于一个字符型指针,a的数据类型也就是char *,它所指向的数据类型是char,a相当于一个字符型指针,那么&a呢?它就相当于一个二级指针,指向字符型数组的指针,所以&a的数据类型也就是char **,它所指向的数据类型是char []。到此为止,我们就明白了为什么a + 1与&a + 1所指向的地址不同了。假设数组名a所指向的地址是2000,那么a + 1指向的是2001,也就是数组a中的第二个字符*(a + 1),而&a + 1指向的就是2005,也就是偏移量为1 * sizeof(a) = 5,也就是数组a之后的第1个字符*(a + 5)。注:*(a + 5)已经超出了数组a的范围
所以,以后遇到这种求指针偏移量的问题,可以如此计算:sizeof(指针所指向的类型) * N
到此为止,我们应该可以彻底明白了,原来指针的运用这么灵活而又复杂。
最近看书感触很深,给大家推荐几本学C语言必读的书籍,《C缺陷与陷阱》、《C专家编程》、《C和指针》、《高质量C++/C编程》(林锐博士的著作),这几本书除了《C和指针》我都看了,写的确实太好了。
发表评论 评论 (9 个评论)
多多交流C的东西,很有意思的。
我是在做socket中发现报文长度处理都用了这种方法,以前在处理bmp图像中没注意。
我感觉,其实很多东西都是细节,一但熟了之后,编程时候脑子里会蹦出一串代码。
多多交流C的东西,很有意思的。
我是在做socket中发现报文长度处理都用了这种方法,以前在处理bmp图像中没注意。
我感觉