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
就看这个吧。