数组与指针的解析 -- 摘自CSDN论坛回复

问题:

比如,现在有一维数组定义如下:
int arr[5]={1,2,3,4,5};

我们都知道 数组名arr是代表数组首元素的地址即arr[0]的地址。 
 那在数组名前面加上取地址符&,即&arr,打印出的地址同样也是arr[0]的地址。

 比如 
   printf("arr=%x\n&arr=%x\n&arr[0]=%x\n", arr, &arr, &arr[0]);

 假设 现在有一个数组指针定义如下:
 int (*p)[5]=NULL;
 p=&arr;// 这样赋值就不会报错。
 p=arr; // 但是这样赋值就会报错。&arr与arr的指向的地址相等的,那么为什么还会报错呢?


 
假设,现在再定义一个二维数组如下:
 int arr2[4][5]={...};
 p=arr2;  // 而这样就不会报错。
 p=&arr2; // 报错。

 
麻烦解释下 “数组名”与“&数组名”分别在一维、二维或更多维数组里的区别和作用? 最好能给出它们在内存,组织的原理或示意图。 
谢谢大家。

回答:

作者:

均陵鼠侠  
账号:sholber

比如,现在有一维数组定义如下:
int arr[5]={1,2,3,4,5};

我们都知道 数组名arr是代表数组首元素的地址即arr[0]的地址。 我很想知道,为什么成千上万的初学者,非得要纠结数组名,以及数组地址的问题。另:数组名代表数组首元素的地址,这个荒唐啊
  那在数组名前面加上取地址符&,即&arr,打印出的地址同样也是arr[0]的地址。

 比如 
    printf("arr=%x\n&arr=%x\n&arr[0]=%x\n", arr, &arr, &arr[0]);

  假设 现在有一个数组指针定义如下:
 int (*p)[5]=NULL;
  p=&arr;// 这样赋值就不会报错。
 p=arr; // 但是这样赋值就会报错。&arr与arr的指向的地址相等的,那么为什么还会报错呢?
这正是我恶心数组名和数组地址之类措辞的原因。因为,只用类型即可解释一切与数组有关的问题。标准说,对于表达式&E,若E的类型是T,则表达式&E的结果是指向T的指针。因为arr是数组,故&arr的结果是指向数组的指针。
标准又说,除非做为运算符sizeof和一元&的操作数,数组类型的标识符将被转换为指向其首元素的指针。因此,p=arr中,arr会被转换为指向其首元素的指针。因为元素的类型是int,故表达式arr转换后的类型是int *,与运算符=的左操作数p的类型不兼容。


 
假设,现在再定义一个二维数组如下:
 int arr2[4][5]={...};
  p=arr2;  // 而这样就不会报错。
 p=&arr2; // 报错。
arr2是一个数组,其元素类型也是数组。从前面说的,arr2被转换为指向其首元素的指针,也就是指向数组的指针(元素类型也是数组嘛),即int (*) [5]与p的类型兼容。相应地,&arr2的结果是指向数组的指针int (*) [4][5],尽管也是指向数组的指针,但与p的类型不兼容。
 
麻烦解释下 “数组名”与“&数组名”分别在一维、二维或更多维数组里的区别和作用? 最好能给出它们在内存,组织的原理或示意图。 
以C中,不存在二维数组和多维数组。所谓的二维数据,就是元素类型是数组的数组(这个过程可以递归进行)。如果用多维数组来理解和解释,反而更迷糊。
谢谢大家。 

更正一下:

标准又说,除非做为运算符sizeof和一元&的操作数,数组类型的标识符将被转换为指向其首元素的指针。

其中,数组类型的标识符改为“数组类型的表达式”。考虑如下声明:
C/C++ code
?
1
struct t {int a [22]; float f;} t [3];

则表达式
C/C++ code
?
1
t [0].a

是数组类型的表达式。它会被转换为指向其首元素的指针:
C/C++ code
?
1
int * p = t [0].a;

=======================

摘录自:https://bbs.csdn.net/topics/391002768?page=1

回答特别简单易懂,一下子就让我 茅塞顿开。

发布了16 篇原创文章 · 获赞 10 · 访问量 15万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览