【问题标题】:Why can't I treat an array like a pointer in C?为什么我不能将数组视为 C 中的指针?
【发布时间】:2012-09-22 11:40:58
【问题描述】:

我在 SO 上经常看到这个问题。也许不是这么多话......但一次又一次地混淆了数组与指针的不同之处。所以我想我会花点时间来问答一些关于这个的问题。

出于本问答的目的,我们将假设一个 32 位系统,并声明了以下内容:

char * ptr = "hello";
char arr[10] = "hello";
int iarr[10] = {0};

以下是我在 SO 上看到的困惑的问题列表。当我看到新的问题时,我会添加到我的问答列表中(其他人也可以随意添加,如果您发现任何错误,请纠正我!)

  1. 指针和数组不是基本一样吗?
  2. 跟进:*(ptr)*(arr),或 ptr[0]arr[0] 给出相同的结果,为什么?
  3. arr&arr 怎么是同一个值?
  4. 跟进:为什么我打印arr+1&arr+1 得到不同的值?

【问题讨论】:

  • @Prætorian - 这绝对是一个很好的链接,我认为这是分开的唯一原因是它是 C++ 特定的。我的目标是 C(因此是标签)和新程序员,我不想将事情与模板以及 C++ 和 C 之间的差异混淆。
  • 请对不赞成票发表评论。我很乐意收拾东西,但让我们讨论一下你不喜欢的东西吧!谢谢。
  • 你错过了一半的图片。您唯一考虑的是静态声明的数组。还有一种; 动态声明的数组。这些是使用变量表达式作为大小参数声明的数组类型,也是传递给函数的类型。在使用 & 运算符和 sizeof() 函数时,动态声明的数组的行为也类似于指针。还值得注意的是,当你将静态数组传递给函数时,它会被转换为动态数组,或者换句话说,将地址复制到指针中。
  • @Zistack:动态数组是一个概念性的东西,没有语言方面的想法。动态数组被认为是语言级别的指针。

标签: c arrays pointers dereference memory-address


【解决方案1】:

1) 指针不是数组。数组不是指针。不要那样想它们,因为它们是不同的。
我怎样才能证明这一点?想想它们在记忆中的样子:

我们的数组 arr 有 10 个字符长。它包含“你好”,但等等,这还不是全部!因为我们有一个静态声明的数组比我们的消息长,所以我们得到了一堆 NULL 字符('\0')是免费的!另外,请注意名称 arr 在概念上是如何附加到连续字符的(它不指向任何东西)。

接下来考虑我们的指针在内存中的样子: 请注意,这里我们指向只读存储器中某个位置的字符数组。

所以虽然arrptr 的初始化方式相同,但它们的内容/位置实际上是不同的。

这是重点:
ptr是一个变量,我们可以指向任何东西,arr是一个常数,它总是引用这个 10 个字符的块。


2) [] 是可用于地址的“添加和引用”运算符。这意味着arr[0]*(arr+0) 相同。所以是的,这样做:

printf("%c %c", *(arr+1), *(ptr+1));

会给你一个“e e”的输出。这不是因为数组是指针,而是因为数组名称arr 和指针ptr 都恰好给了你一个地址。

#2 的关键点: 引用操作符* 和加法和引用操作符[] 并不分别特定于指针和数组。这些运算符只处理地址。


3) 我没有一个非常简单的答案......所以让我们暂时忘记我们的字符数组,看看这个例子来解释一下:

int b;   //this is integer type
&b;      //this is the address of the int b, right?

int c[]; //this is the array of ints
&c;      //this would be the address of the array, right?

所以这很好理解:

*c;   //that's the first element in the array

那行代码告诉你什么?如果我尊重c,那么我会得到一个整数。这意味着简单的c 是一个地址。由于它是数组的开头,它是数组的地址,也是数组中第一个元素的地址,因此从值的角度来看:

c == &c;

4) 让我暂时离开话题……最后一个问题是地址算术混乱的一部分。我曾经看到一个关于 SO 的问题,暗示地址只是整数值......您需要了解在 C 中地址具有类型知识。也就是说:

iarr+1; //We added 1 to the address, so we moved 4 bytes
arr+1;  //we added 1 to the address, so we moved 1 byte

sizeof(int) 基本上是 4,sizeof(char) 是 1。所以“给数组加 1”并不像看起来那么简单。

那么现在,回到问题,为什么arr+1&arr+1 不同?第一个是在地址中添加1 * sizeof(char)=1,第二个是在地址中添加1 * sizeof(arr)=10。

这就是为什么即使它们都“只加 1”,它们会给出不同的结果。

【讨论】:

  • 您对 Q4 的回答与 Q4 有何关系?
  • “这就是为什么ptr 被认为是左值”。不,这不是为什么ptr 被认为是一个左值;毕竟arr 也被认为是一个左值
  • @DavidHeffernan - 我稍微重写了 Q&A4。这是否有助于显示它们之间的关系?只是想明确一点,地址上的 +1 并不总是相同的(取决于地址的类型)
  • 需要改的是Q。再次阅读第四季度。
  • @Mike:我不明白你为什么晚上提到lvaluearrptr 都是 lvalues 但每个表达式都是表示变量或引用的标识符。它似乎与指针与数组的讨论无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
  • 2022-01-02
  • 2020-07-02
  • 1970-01-01
相关资源
最近更新 更多