【问题标题】:what is the role of x = (char *)&a and what does it do?x = (char *)&a 的作用是什么,它有什么作用?
【发布时间】:2019-04-04 09:05:21
【问题描述】:

我有这段代码:

int a;
char *x;
x = (char *) &a;
a = 512;
x[0] = 1;
x[1] = 2;
printf("%d\n");
return 0;

这会打印 513。请解释一下,尤其是第 3 行。

【问题讨论】:

  • 这是展示undefined behavior 的好方法。 printf 电话真的正确吗?
  • no - 它生成一个编译器警告 - main.c: In function 'main': main.c:11:12: warning: format '%d' 需要一个匹配的 'int' 参数 [- Wformat=] printf("%d\n");
  • x = (char *) &a;将整数指针转换为 char 指针 - 至于它的作用,你的猜测和我的一样好?

标签: c pointers char printf


【解决方案1】:

假设您在一台 int 有 4 个字节的机器上。十六进制格式的 512 将是“00 00 02 00”。在小端处理器上,指针指向最低有效字节。要单独设置每个字节,将指向 int 的指针强制转换为指向 char 的指针:x = (char *) &a;因为 char 总是以一个字节编码。现在这四个字节被视为一个由四个字节组成的数组。 x[0] = 1 将最低有效字节设置为“1”;下一个字节设置为“2”(无论如何,行 x[1] = 2; 可以跳过)并且字节 3 和 4 未触及 00 和 00。“a”现在是“00 00 02 01”或 513。 当然在 printf 语句中缺少 'a':printf("%d\n",a);

【讨论】:

    【解决方案2】:

    只要特定机器上的 int 大于 char (并且按照 C 标准它必须如此),您的字节访问本身就不是未定义的。可以确定字节序。可以使用 sizeof 确定类型大小。

    您在这里真正要做的是将整数值的特定字节(代码中的 x 是 char 指针;数组符号 [] 允许您访问整数中的各个字节)设置为某些位模式。如果您再次以整数形式访问如此修改的字节,您的机器的字节序将决定这些位模式代表什么。

    只要您不写入不属于原始整数的字节,代码就不会不正确,除了调用 printf 时缺少真正的 UB 参数。

    剩下的问题是这种操纵可能有什么目的。但这种技术是有用途的。

    【讨论】:

      【解决方案3】:

      第 3 行只是将x 指向a 的地址。作为 C 中的一个特殊规则,我们可以使用字符指针专门访问任何其他变量的各个字节。

      进一步访问x 将更改a 的各个字节,具体方式取决于CPU 字节序。在小端机器上,512 = 0x200,其中两个最低有效字节的值分别为 0x00 和 0x02。 x[0] = 1; 将最低字节更改为 0x01,x[1] = 2; 将值 0x02 写入已包含 0x02 的字节。结果将是 0x201 = 513 十进制。

      这里的问题是printf("%d\n"); 调用了未定义的行为,因为它包含的参数数量不正确。

      总结:代码是乱码,C 语言没有定义这个程序会做什么。它可能会崩溃、打印任何值或根本不打印任何值。思考它为什么以某种方式表现并不是有意义的实践。而是专注于学习如何避免未定义的行为错误。

      【讨论】:

      • 链接 x[0] = 1 的好地方; x[1] = 2;在小端机器上到值 513,非常尖锐
      • 我不同意“胡言乱语”。对 printf 的调用是 UB,否则它是工作代码。按字节操作内存并不少见,也是 C 语言的优势(和危险)之一。
      猜你喜欢
      • 2011-01-14
      • 2019-04-26
      • 2016-04-29
      • 2017-03-02
      • 2012-10-04
      • 1970-01-01
      • 2010-11-09
      • 2017-06-20
      • 2019-12-25
      相关资源
      最近更新 更多