Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
未知的C代码输出_C_Pointers_Undefined Behavior_Unsigned Integer - Fatal编程技术网

未知的C代码输出

未知的C代码输出,c,pointers,undefined-behavior,unsigned-integer,C,Pointers,Undefined Behavior,Unsigned Integer,下面的代码如何给出20362036的答案 以下C代码的输出是什么?假设x的地址是十进制的2000,整数需要四个字节的内存 int main() { unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}; printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3); } 虽然x和x[0]的地址相同,但它们的类型不

下面的代码如何给出20362036的答案

以下C代码的输出是什么?假设x的地址是十进制的2000,整数需要四个字节的内存

int main()
{ 
   unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6}, 
                           {7, 8, 9}, {10, 11, 12}};
   printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3);
}
虽然x和x[0]的地址相同,但它们的类型不同,因此大小也不同

您应该在主函数的末尾添加return 0。此外,您的打印声明应如下所示:

printf("%p, %p, %p\n", (void *)(x+3), (void *)*(x+3), (void *)(*(x+2)+3));
/*      ^^  ^^  ^^^^   ^^^^^^^^^   ^  ^^^^^^^^        ^^^^^^^^^        ^ */

对于定义良好的bahviour。

正如您刚刚发现的那样,如果您不发布精心编制的代码,人们可能会对您有点苛刻。要打印地址,请使用%p或PRIXPTR和uintptr的casts等宏

仅使用%p,您的代码可能应为:

#include <stdio.h>

int main(void)
{ 
    unsigned int x[4][3] =
    {
        {  1,  2,  3 }, {  4,  5,  6 }, 
        {  7,  8,  9 }, { 10, 11, 12 }
    };
    printf("%p\n", (void *)x);
    printf("%p, %p, %p\n", (void *)(x+3), (void *)(*(x+3)), (void *)(*(x+2)+3));
    return 0;
}
十六进制0x24当然是36位小数。

编辑:正如乔纳森·莱夫勒指出的,我应该在打印%p之前将其转换为void*

也许这将澄清内存寻址方面的情况:

#include <stdio.h>

int main() {
    unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}};

    // Output: Address, 1
    printf("%p, %u\n", (void*)(x),      **x);

    // Output: Address + 12, 4
    printf("%p, %u\n", (void*)(x+1),    **(x+1));

    // Output: Address + 24, 7
    printf("%p, %u\n", (void*)(x+2),    **(x+2));

    // Output: Address + 4, 2
    printf("%p, %u\n", (void*)((*x)+1), *(*(x)+1));

    return 0;
}

未定义的行为当您试图用%u打印x+3时,您有未定义的行为……没错,这是UB,但可能仍然有一些道理。@asimes:UB与问题的目的无关,而不是根本问题。代码可以很容易地修复,然后再进行推理。UB是一个C的新手可以轻松制作的。请记住,并不是所有提出这一问题的人都是专家。@asimes:我同意——如果问题本质上是关于UB的,那么就没有必要深入研究,或者这样做也没有什么意义。那么这些问题问你从x=++x+x++;,得到了什么;?等等都是毫无意义的。这不属于那个类别,我想你可能会同意。严格地说,在使用%p打印之前,你应该将指针转换为void*。在当前的机器上,这不太可能是一个实际问题,但我在一台机器上学习了C语言,在出现void*之前的几天里,内存位置的char*地址的值与同一内存位置的int*地址的值不同,我可以补充一句——这告诉你这是很久以前的事了——所以char*是“通用指针”。@JonathanLeffler,说实话,我根本没有意识到这一点。我很好奇,在什么情况下,这会对你学习的机器产生影响?IIRC,如果你将内存位置的char*地址打印为hex,你会得到一个值,比如0x80049268;如果为同一内存位置打印int*地址,则会得到一个值0x00049268。这是很久以前的事了,当我们得到一个额外的1MIB内存时,我们非常高兴,它将机器上的内存增加了一倍。这意味着程序要使用1.25MIB,而不仅仅是0.25MIB,因为o/s占用了大约0.75MIB。因此,使用32位地址的高位表示它是字节地址而不是字地址不是问题;有很多未使用的位。十六进制中可能还有一个“因子2”;我现在不记得了,它可能是一种稍微不同的编码方式。但有一点不同。不声明extern char*malloc是一个可怕的bug;在使用它之前,这是在几天前有一个声明它。在这样的环境中,你要学会小心。@JonathanLeffler,哇,我很高兴我三年前学会了C。。。坦白地说,int*如何不给出0x80049268,我仍然不清楚。我假设那个上下文中的字是16位,而字节是8位?即使这是真的,我仍然不明白地址的差异是从哪里来的
0x7fff5800a440
0x7fff5800a464, 0x7fff5800a464, 0x7fff5800a464
#include <stdio.h>

int main() {
    unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}};

    // Output: Address, 1
    printf("%p, %u\n", (void*)(x),      **x);

    // Output: Address + 12, 4
    printf("%p, %u\n", (void*)(x+1),    **(x+1));

    // Output: Address + 24, 7
    printf("%p, %u\n", (void*)(x+2),    **(x+2));

    // Output: Address + 4, 2
    printf("%p, %u\n", (void*)((*x)+1), *(*(x)+1));

    return 0;
}
#include <stdio.h>

int main() {
    unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}};

    printf("%p, %u\n", (void*)(x),      **x);       // Output: Address, 1
    printf("%u\n",                      x[0][0]);   // Output: 1

    printf("%p, %u\n", (void*)(x+1),    **(x+1));   // Output: Address + 12, 4
    printf("%u\n",                      x[1][0]);   // Output: 4

    printf("%p, %u\n", (void*)(x+2),    **(x+2));   // Output: Address + 24, 7
    printf("%u\n",                      x[2][0]);   // Output: 7

    printf("%p, %u\n", (void*)((*x)+1), *(*(x)+1)); // Output: Address + 4, 2
    printf("%u\n",                      x[0][1]);   // Output: 2

    return 0;
}