繁体   English   中英

没有完全理解 output 非常小的C 程序使用void*/char* 引用和int + 指针运算

[英]Don't fully understand the output of very small C program using void*/char* to refer to and int + pointer arithmetic

我无法完全理解为什么以下代码片段的 output 在 onlinegdb.com 和 visual studio 上都是2 ,而我预计会出现垃圾/崩溃值

我知道小端和大端是什么。 我的 comp 显然应该是 little endian,因为它是一个 32 位的英特尔核心双核。

我有 512,在 little endian 中是:

0000 0000 0010 0000 0000 0000 0000 0000
^         ^         ^
p         p+1       p+2

p将指向第一个0000p + 10010 当我打印 2 来自0010时,但是使用%d它不应该打印0010 0000 0000 0000 0000 0000 xyzw rstu的十进制表示(带有 8 个随机位)?

问:默认情况下,它是否将最后一位修补为 0,还是只是运气好,取 0 是因为它们使用了最后一个值? 它不应该是未定义的吗?

#include <stdio.h>

int main()
{
    int x = 512;
    void *p = &x;
    printf("%d\n", *((char*)p + 1));
    return 0;
}

对于%d ,它不应该打印 0010 0000 0000 0000 0000 0000 xyzw rstu(8 个随机位)吗?

不,不是你的情况。

你这样做:

*((char*)p + 1)

这意味着以下内容:

  1. p并将其转换为char *
  2. Advance 1 position(转换为char *表示 1 个字节)。
  3. 取消引用那个(仍然是char * ),获得 1 个字节。
  4. 你得到的字节是2。
  5. 当传递给printf时,字节现在隐式转换为int

换句话说,这就是发生的事情:

0000 0000 0100 0000 0000 0000 0000 0000
          ^^^^^^^^^
          (char*)p+1
          vvvvvvvvv
          0100 0000 [0000 0000 0000 0000 0000 0000]
                     promotion to int when calling printf

所以这就是为什么您看不到“8 个随机位”的原因。


另一方面,如果您要做这样的事情:

// notice the second cast to (int*) AFTER advancing 1 byte
printf("%d\n", *(int*)((char*)p + 1));

那么这将是未定义的行为 可能已经看到了一些随机位(这意味着更大的值),或者您可能运气不好得到了零,但由于它是 UB,您不能真正期望从中得到任何有意义的东西。

我有 512,在小字节序中是:0000 0000 0010 0000 0000 0000 0000 0000

正确,除了它实际上是 0000 0000 0000 0010。Endianess 是字节顺序,而不是半字节顺序。

p+1 到 0010

正确,它指向字节0000 0010。

当我打印 2 来自 0010 时,但是使用 %d 它不应该打印 0010 0000...

不,因为当您取消引用 8 位char时,您在 8 位临时 object 中以值 2 结束。

事实证明,诸如printf类的可变参数函数将小的 integer 参数提升为int默认参数提升),而不管格式说明符如何。 因此,您最终得到一个值为2int ,然后printf打印该值。

您可能希望在打印字节之前复制该字节:

int main()
{
    const int x = 512;
    uint8_t * p = (uint8_t *)(&x);
    for (unsigned int i = 0u; i < sizeof(int); ++i)
    {
        const uint8_t value = *p++;
        printf("%d\n", value);
    }
    return 0;
}

将 memory 复制到变量中可防止编译器将位置方程解释为 4 字节 integer(如您的示例所示)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM