【问题标题】:The double pointer points to the int variable to overwrite the memory [duplicate]双指针指向int变量以覆盖内存[重复]
【发布时间】:2018-03-23 03:41:17
【问题描述】:

我直接放代码了。

#include <stdio.h>
struct A
{
    int a;
    int b;
};
int main()
{
    struct A test;
    double *p = (double *)&(test.a);
    *p = 5;

    printf("variable a: %d\n", &test.a);
    printf("variable b: %d\n", &test.b);
    return 0;
}

我在centos7中运行这段代码,编译器是gcc4.8.5。而我的电脑使用little ending来存储。

如您所见,变量b 的内存将被覆盖,我预计a0x0000 0005b0x0000 0000

但答案是:

variable a: 0
variable b: 1075052544

为什么变量a0x 0000 0000b0x4014 0000

【问题讨论】:

  • 这是未定义的行为。此外,double 5 对应于 64 位整数 0x4014000000000000,因此您可能可以弄清楚发生了什么。提示:double 可以大于int
  • 你得到了意想不到的结果,因为你对你的编译器撒了谎,它想出了一个办法来报复你。你告诉编译器&amp;(test.a) 是一个double 的地址,但它是一个整数的地址。
  • 你可以调整优化设置并让你的编译器编译代码,结果也是else
  • @Bathsheba 只是写在这里,输出与代码不匹配,所以,你为什么要推翻我的反对意见?!
  • 该代码是一个严格的别名违规,因此是完全未定义的行为。对未定义行为的影响进行推理是毫无意义的。

标签: c pointers memory int double


【解决方案1】:

您的代码的行为是未定义

一旦您将p 设置为非double 类型的地址,就无法取消引用它。

要查看您的编译器对此输入做了什么,请检查生成的程序集。

【讨论】:

  • 在我的电脑里,int占4个字节,double占8个字节,我用双指针指向int和赋值,它应该覆盖变量b的值,所以我认为b应该是5、a应该为0。而1075052544是一个固定值,不会随着每次运行或改变优化而改变。
  • 你想怎么想就怎么想。这显然不是正在发生的事情。事实仍然是行为未定义。
  • 双5对应64位整数0x4014000000000000。所以我得到b0x4014 0000,变量b的值是4字节的另一半。跨度>
  • @UKeeySDis:您可以通过将 64 位整数设置为给定值、将双精度值设置为另一个值并调用 memcmp 来验证这一点。所有完美定义的行为。
  • 这真是个好主意,我验证了。但是为什么双5对应64位整数0x4014000000000000?它是如何存储的?非常感谢。
【解决方案2】:

您的代码行为未定义。

Clang 编译器生成警告信息:

source_file.c:13:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
    printf("%d\n", &test.a);
            ~~     ^~~~~~~
source_file.c:14:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
    printf("%d\n", &test.b);
            ~~     ^~~~~~~

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-19
    • 2019-03-03
    • 2012-11-17
    • 1970-01-01
    • 2015-07-01
    • 2014-09-05
    • 1970-01-01
    相关资源
    最近更新 更多