C语言指针问题,求高手解惑
1.假设有一维int a[5],a代表数组的地址,&a有什么意义呢,
为什么这里a和&a的值相等呢?
2.假设有二维数组int a[2][3],a和&a也相等吗?
3.这个是谭浩强C程序设计里的例题:
#include<stdio.h>
int main()
{
int a[4]={1,3,5,7};
int (*p)[4];
p=&a; //第六行
printf("%d\n",(*p)[3]);
return 0;
}
书中说第六行只能写成p=&a,而不能是批p=a,
书中说p=a 表示p的值是&a[0],指向a[0].
p=&a表示p指向一维数组(行),(*p)[3]是p所指向行中序列为3的元素。
但实际上我用VC6.0调试时两个都能得到7的答案,只不过当p=&a时,没有报警,
而当p=a时,编译器有预警信息: warning C4047: '=' : 'int (*)[4]' differs in levels of indirection from 'int *'
难道谭浩强的这本书是按旧的C标准写的吗?还是说编译器允许这样的写法?
4.a和&a无条件等价吗?
如果你非要较真,那么
在C中, 在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址。 它的类型取决于数组元素的类型: 如果它们是int类型,那么数组名的类型就是“指向int的常量指针“。
看到这里我想应该就知道为什么 会有I 和 III式的结果了。
对于II 和 IV 则是特殊情况,在《C和指针》p142中说到,在以下两中场合下,数组名并不是用指针常量来表示,就是当数组名作为sizeof操作符和单目操作符&的操作数时。 sizeof返回整个数组的长度,而不是指向数组的指针的长度。 取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量的指针。
** 所以&a后返回的指针便是指向数组的指针,跟a(一个指向a[0]的指针)在指针的类型上是有区别的。**
(1)C语言就是这么规定的,C语言是一种很垃圾很奇葩的语言,因为早期计算机很差,所以实现的编译器都很差,那么语言就不能太复杂。C语言遗留了很多不可思议的语法。
比如说
int a[4]={1,3,5,7};
printf("%d", 2[a]);
这样也能输出5,是不是很奇怪。
其实没什么奇怪的,a[2] = &a + 2而2[a] = 2 + &a。
(2)是的
(3)谭浩强的书不会教你真正的知识,只会教你奇技淫巧。你要做的是把程序写对,而不是如何故意乱写但是编译器不报错。
好比2[a]是合法的,if (a = 1)也是合法的,但是这种写法只能坑爹。
(4)当然不是,前提是a是一个数组。
如果你用的C/C++编译器越现代,它在兼容遗留代码的同时,给不规范的代码的警告就越多。
你把谭X强的代码贴在VS2013中,能收到一堆警告呢。
#include <stdio.h>
02.
03.int a[2] = {1,2};
04.int main(){
05. printf("a = %p\n", a); // I
06. printf("&a = %p\n", &a); // II
07. printf("a + 1 = %p\n", a + 1);// III
08. printf("&a + 1 = %p\n", &a + 1);// IV
09.
10. return 0;
11.}
caozhy威武霸气,我想问下如何才能把程序写对呢??能推荐一本快速入门的书籍吗?
要把程序写对那很简单,就是去写程序。不是去写那些无病呻吟的小程序,而是去写实实在在的程序。
当你的程序越写越多越写越大,你就自然会恨透那些没事找事故弄玄虚的东西,你就会知道规避这些坑。
当然,真爱生命,远离C语言是上策。
python大法好,C#大法好,拒用C/C++保平安。
谭浩强的问题是价值观的问题,如果你觉得他的书是真理,你和我们不是一个世界的,那也没什么好说的了。
首先,从C4047这个错误类型描述上可知p和a的类型是不一样的,
从代码第4行可知你定义了一个一维数组(数组中包含4个整型常量),
从代码第5行可知你定义了一个数组型指针(指针p指向一个大小为4的数组)
当你执行p=&a赋值操作时,编译器不报错,因为&a本身就是一个大小为4的数组的首地址,也就是说p和&a的变量类型其实是一样的
而当你执行p=a赋值操作时,编译器报错,因为a虽然是一个地址(指针),但未知大小,也就是说此时p和a的变量类型不同,不能直接赋值,
但是结果没有出错,是因为程序执行过程中发现a的大小就是4,所以结果不会发生错误。
the C Programming Language
就看这个吧。