在C++中数组和指针的区别之前,比如一个数组int a[10],我一直把a理解成一个指针,就是int*,那么,int a[10][10]中的a自然就是int**,但是,这段程序却无法编译:
int mm[5][5]; int **gg(int k) { return mm; } 却无法编译,必须改成 typedef int(*dt)[5]; dt gg(int k) { return mm; } 或者 int (*gg(int k))[5] { int (*p)[5] = NULL; return p; } 这点很令人不解,其实我一直的理解都错了。 来看百度知道上的一个问答: 问: 问题补充:int a[5]={1,2,3,4,5};这里的a不是说代表一个常量吗,怎么可以&a这样操作呢, 搞得我以为是等同于&a[0]。 答: 在一般上下文中,对数组的引用会退化为指针,例如: int a[5]; int *p = a + 1; 在这代码中,第二行对a的引用退化为一个指针,指针类型为int。 在&a这样的表达式中数组退化为指针的规则则不再使用。作为一个整体,&a也表示一个指 针,它与a不同的就是:a的指针类型为int,而&a的指针类型为int[5]。 用这段理解来解释楼主的问题就不难了 即 int *ptr=(int *)(&a+1); 这句话 &a+1是对于int[5]类型的加1,然后再转成(int*)时,其实ptr指向了a[5]! 接着再减1,自然输出了a[4]。 ------------------------------------------------- 补充知识: 1)在c语言中,并没有真正的数组类型,大部分对数组的引用会退化为指针 2)多位数组的情况: 例如int a[x][y]; 则a退化为指针类型是int[y],&a的类型则是int[x][y] 3)数组退化为指针的规则不能递归应用。数组的数组退化为数组的指针,而不是指针的指针。 如果你向函数传递一个二维数组,例: int a[x][y]; f(a); 则f必须声明成 int f(int a[][y]); 或 int f(int (*a)[y]); 而不能是 int f(int **a); ----------------------------------- 楼主,你所听说的a称作常量指针,这都是骗小孩子玩意,要想真正理解数组,必须明白在 表达式中出现a,a退化为指针 “数组名“之所以为常量是因为它不能被赋值,但!!数组不是指针!!。数组只是在表达 式中出现时退化为指针,而指针&p与数组&a则是截然不同的行为,这正说明数组不是指针。 例如 int *p = (int *) 111; 那么p是111,而&p则是p的地址(可能为0x00122222), 但对于数组 int a[6]; 若a是0x00123333,则&a也是0x00123333,只是这两者的指针类型不同 ----------------------------------------------- 另外,在参数传递时数组也经常令人困惑 例如int f(char a[]);这种类型的声明,编译器内部将它当作int f(char *a); 所以可以对它传入指针。若对它传入数组,则数组退化为指针所以参数类型检验才能通过。 所以你即使声明int f(char a[4]);看上去a是个数组,在函数体内写a = 1;则违反了数组 名是常量的规则,其实a = 1;是允许的因为int f(char a[4]);在编译器看来是int f(char *a); 其中的4被忽略了 最后一点要注意的是在一个源文件中定义int a[5]; 而在另一个源文件1中写下extern char *a是不合法的 因为数组与指针是两个类型 ----------------------------------------------- 最后罗索一句,楼主你所说&a[0]倒是和一般上下文中a等价都是int型指针。而&a则是int[5]型指 针,我一直强调这点你明白了没? 希望楼主好好学习,c中的数组可不好理解 |
|