【问题标题】:what is the output? Please explain, considering i am a novice in c [closed]输出是什么?请解释一下,考虑到我是c的新手[关闭]
【发布时间】:2011-10-17 12:09:48
【问题描述】:
int a[3][4] = {
             1,2,3,4,
             5,6,7,8,
             9,10,11,12,
           };
printf("%u %u %u \n", a[0]+1, *(a[0]+1), *(*(a+0)+1));

【问题讨论】:

  • 这个问题听起来很可疑。为什么需要这个?
  • 运行它并找出答案。
  • 您至少可以运行它,试一试,然后过来询问。这样会好很多。
  • @missingno:我正在准备一些面试,所以想出了这个问题。
  • @eckes :感谢您的努力 :) 但我所指的书给出的答案是“1006 4 4”。有什么想法,怎么来的?

标签: c arrays pointers multidimensional-array


【解决方案1】:

C 中数组速成课程的时间到了。

首先,让我们修复数组的初始化器:

int a[3][4] = {
                { 1,  2,  3,  4},
                { 5,  6,  7,  8},
                { 9, 10, 11, 12}
              };

这定义了 int 的 4 元素数组的 3 元素数组。 表达式 a 的类型是“int 的 4 元素数组的 3 元素数组”。

现在是引起头痛的部分。除非它是 sizeof 或一元 & 运算符的操作数,或者如果它是用于在声明中初始化另一个数组的字符串文字,则数组类型的表达式将其类型隐式转换(“衰减”)为指针类型。

如果表达式a在代码中单独出现(例如在printf("%p", a);这样的语句中,其类型从“int的4元素数组的3元素数组”转换为“指针指向int的四元数组”,或者int (*)[4]。同理,如果代码中出现a[i]这个表达式,其类型由“int的四元数组”(int [4])转换为“指向int" (int *) 的指针。如果aa[i]sizeof& 的操作数,则不会发生转换。

类似地,数组下标是通过指针算术完成的:表达式a[i] 被解释为好像写成*(a+i)。您从数组的底部偏移i 元素并取消引用结果。因此,a[0]*(a + 0) 相同,与*a 相同。 a[i][j] 与写 *(*(a + i) + j) 相同。

下表总结了以上所有内容:

表达式类型衰减为结果值 ---------- ---- --------- ----- a int [3][4] int (*)[4] 数组第一个元素的地址 &a int (*)[3][4] n/a 同上,但类型不同 *a int [4] int * 同上,但类型不同 a[0] int [4] int * 同上 *(a+0) int [4] int * 同上 a[i] int [4] int * 第 i 个子数组的第一个元素的地址 *(a+i) int [4] int * 同上 &a[i] int (*)[4] n/a 同上,但类型不同 *a[i] int n/a 第 i 个子数组的第 0 个元素的值 a[i][j] int 第 i 个子数组的第 j 个元素的值 *(a[i]+j) int 同上 *(*(a+i)+j) int 同上

希望这应该为您提供确定输出应该是什么所需的一切。但是,printf 语句应该写成

printf("%p %d %d\n", (void *) a[0]+1, *(a[0]+1), *(*(a+0)+1));

【讨论】:

  • @john Bode:是的,我明白了,感谢您抽出宝贵时间。 :)
【解决方案2】:
$ gcc -Wall -o output output.c
output.c: In function ‘main’:
output.c:5:5: warning: missing braces around initializer [-Wmissing-braces]
output.c:5:5: warning: (near initialization for ‘a[0]’) [-Wmissing-braces]
output.c:9:5: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat]

因为二维数组被初始化为好像它只有一维。

完整程序,供参考:

#include <stdio.h>

int main()
{
    int a[3][4] = {1,2,3,4,
                   5,6,7,8,
                   9,10,11,12,
    };
    printf ("%u %u %u \n", a[0]+1, *(a[0]+1), *(*(a+0)+1));
    return 0;
}

【讨论】:

    【解决方案3】:

    首先,您的初始化是错误的:您将它初始化为一维数组,而您声明了一个二维数组。

    其次,让我们看看你的代码是做什么的。

    a 是一个二维数组,所以a[0] 的类型是int[4](一维数组),表示多维数组的第 0 列,并且(大部分)与指向列的前导元素的指针。现在使用地址算术:a[0] + 1 是指向第 0 列中前导元素之后的元素的指针(表示为指向它的指针),即指向第 0 列中第 1 个元素的指针。那是第二个警告出现的地方,说你对printf 的论点是int* 而不是unsigned int

    接下来,*(a[0]+1) 取消引用指向第 0 列的第 1 个元素的指针。这(通常)相当于a[0][1]

    接下来,*(*(a+0)+1)) 相同,因为*(a+0)a[0] 相同。

    (为了理解这一切,你需要知道一些基础知识:在C语言中*(x + y)x[y]是一样的,一维数组本质上和指向它的前导元素的指针是一样的.)

    关于你的书和现实的区别:第一个输出值只是一个指针,所以它可以是任意值,这取决于你的数组在内存中的位置。关于其他两个值,问题取决于错误的初始化程序如何填充数组。

    【讨论】:

    • 我同意一个人可能不应该初始化这样的东西,但在强烈的意义上它并不是“错误的”。该标准明确允许这种“平面”初始化。
    猜你喜欢
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 2021-10-07
    相关资源
    最近更新 更多