为什么我不能像 C 中的指针一样对待数组? [英] Why can't I treat an array like a pointer in C?

查看:24
本文介绍了为什么我不能像 C 中的指针一样对待数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

这里有一个问题列表,可以推测我在 SO 上看到的混淆.当我看到新的时,我会添加到我的问答列表中(其他人也可以随意添加,如果您发现任何错误,请纠正我!)

  1. 指针和数组不是基本一样的东西吗?
  2. 跟进:*(ptr)*(arr),或 ptr[0]arr[0]] 给出同样的东西,为什么?
  3. 为什么 arr&arr 是相同的值?
  4. 跟进:为什么打印 arr+1&arr+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;//这是整数类型&b;//这是int b的地址吧?int c[];//这是整数数组&c;//这将是数组的地址,对吗?

所以这很容易理解:

*c;//这是数组中的第一个元素

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

c == &c;

<小时>

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

iarr+1;//我们给地址加了1,所以我们移动了4个字节arr+1;//我们给地址加了1,所以我们移动了1个字节

基本上 sizeof(int) 是 4 而 sizeof(char) 是 1.所以向数组添加 1"并不像看起来那么简单.

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

这就是为什么即使它们都只加 1",它们给出了不同的结果.

I see this question a lot on SO. Maybe not in so many words... but time and again there is confusion on how arrays are different from pointers. So I thought I would take a moment to Q&A a few points about this.

For purposes of this Q&A we're going to assume a 32-bit system and the following have been declared:

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

Here's a list of questions that surmise the confusion I see on SO. As I see new ones I'll add to my list of Q&A (others feel free to as well, and correct me if you see any mistakes!)

  1. Isn't a pointer and an array basically the same thing?
  2. Follow up: both *(ptr) and *(arr), or ptr[0] and arr[0] give the same thing, why?
  3. How come arr and &arr is the same value?
  4. Follow up: why do I get a different value printing arr+1 vs &arr+1?

解决方案

1) Pointers are not arrays. Arrays are not pointers. Don't think of them that way because they are different.
How can I prove this? Think about what they look like in memory:

Our array arr is 10 characters long. It contains "Hello", but wait, that's not all! Because we have a statically declared array longer than our message, we get a bunch of NULL characters ('\0') thrown in for free! Also, note how the name arr is conceptually attached to the contiguous characters, (it's not pointing to anything).

Next consider how our pointer would look in memory: Note here we're pointing to a character array some place in read only memory.

So while both arr and ptr were initialized the same way, the contents/location of each is actually different.

This is the key point:
ptr is a variable, we can point it to anything, arr is a constant, it will always refer to this block of 10 characters.


2) The [] is an "add and deference" operator that can be used on an address. Meaning that arr[0] is the same as saying *(arr+0). So yes doing this:

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

Would give you an output of "e e". It's not because arrays are pointers, it's because the name of an array arr and a pointer ptr both happen to give you an address.

Key point to #2: The deference operator * and the add and deference operator [] are not specific to pointers and arrays respectively. These operators simply work on addresses.


3) I don't have an extremely simple answer... so let's forget our character arrays for a second and take a look at it this example for an explanation:

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?

So that's pretty understandable how about this:

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

What does that line of code tell you? If I deference c, then I get an int. That means just plain c is an address. Since it's the start of the array it's the address of the array and also the address of the first element in the array, thus from a value standpoint:

c == &c;


4) Let me go off topic for a second here... this last question is part of the confusion of address arithmetic. I saw a question on SO at one point implying that addresses are just integer values... You need to understand that in C addresses have knowledge of type. That is to say:

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

Basically the sizeof(int) is 4 and the sizeof(char) is 1. So "adding 1 to an array" is not as simple as it looks.

So now, back to the question, why is arr+1 different from &arr+1? The first one is adding 1 * sizeof(char)=1 to the address, the second one is adding 1 * sizeof(arr)=10 to the address.

This is why even though they are both "only adding 1" they give different results.

这篇关于为什么我不能像 C 中的指针一样对待数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆