【问题标题】:Why is * needed with pointers to arrays?为什么 * 需要指向数组的指针?
【发布时间】:2014-01-26 04:19:56
【问题描述】:
#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
int main()
{
    int x[][2] = { {1,2},{3,4},{5,6},{7,8} };
    int i, j;
    printf("%d \n", x);
    for (i = 0; i <= 3; i++)
    {
        printf("%u %u\n", x + i, *(x + i));
    }
    for (i = 0; i <= 3; i++)
    {
        for (j = 0; j <= 1;j++)
        printf("%u %u\n", *(x + i + j), *(*(x + i) + j));
    }
    return 0;
}

输出:

3217317712 3217317712
3217317720 3217317720
3217317728 3217317728
3217317736 3217317736
3217317712 1
3217317720 2
3217317720 3
3217317728 4
3217317728 5
3217317736 6
3217317736 7
3217317744 8

现在,当我打印 (x+i)*(x+i) 时,结果相同。
但是,当我打印 *(x+i+j)*(*(x+i)+j) 时,它给了我不同的结果。
如果(x+i)*(x+i) 被评估为相同的值,为什么我在第二种情况下会得到不同的结果?

【问题讨论】:

  • 您正在打印指针,但告诉 printf 它们是整数。这是未定义的行为,然后可能会发生各种奇怪的事情。
  • @ThomasPadron-McCarthy 格式化指向整数的指针会在 64 位系统中丢失一些位。但这不是未定义的行为。
  • @oyss:我确实相信给 printf 提供不一致的参数会产生未定义的行为。引用标准(委员会草案——2007 年 9 月 [原文如此] 7,第 280 页)(我的免费草稿副本):“如果任何参数不是相应转换规范的正确类型,则行为未定义。”
  • 为什么 (x+i) 和 *(x+i) 没有区别?我就是不明白!
  • 阅读comp.lang.c FAQ的第6部分。

标签: c arrays pointers dereference


【解决方案1】:

简答:

表达式 (x+i)*(x+i) 都是指针。它们有不同的类型,但它们指向内存中的同一个地方。

尝试写一个更长的答案:

当您在 C 程序中使用数组的名称时,它(有一些例外)被转换为指向其第一个元素的指针。因此,如果 a 是一个整数数组,则名称 a 将被转换为指向整数的指针:

int a[3];
int *p = a; // Correct type

您的 x 是一个数组数组。当您在程序中使用名称 x 时,它会转换为指向其第一个元素的指针,该元素是一个数组,因此您会得到一个指向数组的指针:

int x[][2] = { {1,2},{3,4},{5,6},{7,8} };
int (*p)[2] = x; // Correct type

那么当您将指针解引用运算符 * 添加到 x 时会发生什么?记住表达式 x 变成了一个指向数组的指针,所以当你跟随指针指向它所指向的东西时,使用 *x,你会得到一个数组,在这个case 两个整数的数组。但是,与 C 中的往常一样,该数组表达式被转换为指向其第一个元素的指针,因此您会得到一个指向整数的指针:

int *p2 = *x; // Correct type

但是这个指针p2和上面的指针p指向内存中的同一个地方。只是他们的类型不同而已。 p 指向第一个二整数数组,p2 指向该数组中的第一个整数。那是同一个地方。

x + i 只是表示“将指针 x 向前推进 i 元素”,不改变类型,所以就像表达式 x*x 给出了指向内存中相同位置的指针,(x + i)*(x + i ) 指向同一个地方。

请注意,x 是数组数组,而不是指向数组的指针数组,并且程序中的表达式 x 给出了指向数组的指针,而不是指向指针的指针。如果 x 是一个包含指针的数组,则表达式 x 会给你一个指向指针的指针,在 的情况下, x*x 会有所不同。

【讨论】:

  • @user3152736:你具体想什么?该示例中的前四个指针都指向内存中的同一位置,即数组 x 数组的开头。第五个指针指向变量y。您打印的最后一件事是 x 开头的数字。
  • “但是,像往常一样,在 C 语言中,该数组表达式被转换为指向其第一个元素的指针” 嗯,“通常”的意思是在这种情况下使用它的上下文中,是的。但并非在所有情况下。
  • @newacct:是的,这就是我写“有一些例外”的原因。但可能需要注意的是,例如,使用 & 运算符不会转换为指针,因此表达式 &x 不会首先创建指针,存储它在某处,然后创建一个指向该位置的新指针。也许这就是 user3152736 在上面的评论中想知道的,为什么不只是 x*x 而且 &x 指向内存中的同一个地方?
【解决方案2】:

x+i*(x+i) 都是指针类型,第一种情况是 int**,第二种情况是 int*,因为它是包含数组指针的数组指针。所以最正确的地址是*(*(x+i)+j),它会给你号码。

【讨论】:

  • 注意指针和数组的区别。这里没有包含指针的数组!它只是一个数组的数组,数组的名称被转换为指向数组的指针。
  • 是的,我的错,刚刚检查过。
  • x+1 不是int**,而是int (*)[4][2]
  • x+i 不是 int**。这是int (*)[2]。而*(x+i) 的类型为int [2],是数组类型,而不是指针类型,尽管在某些上下文中它可以转换为指针类型。
猜你喜欢
  • 2010-10-28
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多