【问题标题】:Difference between pointer to pointer and pointer to 2d array指向指针和指向二维数组的指针之间的区别
【发布时间】:2014-08-01 12:35:29
【问题描述】:
  1. 如果我有一个二维数组 B 定义为:

    int B[2][3] = {{1,3,5},{2,4,6}};
    

    int **p = Bint (*p)[3] = B 一样吗?

  2. int **f = B; printf("%d ",*f+1);

    给出5 作为输出,而printf("%d ",*f) 给出1 作为答案。为什么 是这样吗?

  3. printf("%d ",**f);

    返回分段错误!为什么?

【问题讨论】:

  • 是的!这是一个错字。更正了
  • 这是指向一维数组的指针,而不是指向二维数组的指针。
  • This 可能有点帮助。

标签: c pointers multidimensional-array pointer-to-pointer


【解决方案1】:
  1. 没有。 int **p = B; 是一个错误。 (编译错误和逻辑错误)。 int ** 必须指向 int *。但是,B 中没有存储int *B 是一组不涉及指针的连续 ints。

  2. int **f = B; 必须给出编译错误。结果生成的任何可执行文件的行为都是完全未定义的。

  3. 见 2。


解释为什么您可能会看到15。 (C 标准没有定义这一点,但无论如何你的编译器都在前面)。可能您的编译器将该行视为

int **f = (int **)B;

然后表达式*f 将从B(实际上保存ints)的存储中读取字节,并假设这些字节是构成指针表示的字节。这是进一步的未定义行为(违反严格别名规则)。可能这样的结果是*f 是指向地址0x00000001 的指针。

然后您使用%d 打印一个指针,从而导致进一步的未定义行为。您看到1 是因为您的系统使用与传递int * 相同的方法将int 传递给printf

当您将 1 加到 (int *)0x00000001 时,您会得到 (int *)0x00000005,因为递增指针意味着指向该类型的下一个元素。

当您取消引用此指针时,它会导致段错误,因为该地址超出了您的有效地址空间。

【讨论】:

  • 在 C99 上它只是给出警告 warning: initialization from incompatible pointer type [enabled by default]
  • @Dubby 技术术语是诊断,程序格式错误。之后是否要继续由单个编译器决定(并且该行为已超出 C 标准所涵盖的范围)
  • 所以基本上像char *argv[] 这样的声明不是二维数组,即与char argv[m][n] 不同?
  • @Dubby;是的。这是不一样的。指针不是数组。
  • 不,这是一个函数参数,其含义与变量声明不同。 see here了解详情。
【解决方案2】:

1) int **p = b 是否与 int (*p)[3] = b 相同? - 编号int **p = b 是一个错误。

因为这里int **p 是指向整数的指针,而int (*p)[3] 是指向3 个整数数组的指针!

2) int **f = B; 这是一个错误,可能导致未定义的行为!

3) printf("%d ",**f); - 与 (2) 相同。 int **f = B; 是错误的,所以未定义的行为!

注意:为避免此类错误,请在编译器选项中启用一些警告标志并尝试!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    相关资源
    最近更新 更多