gpt4 book ai didi

c++ - 一种独特的数据转换类型

转载 作者:行者123 更新时间:2023-11-30 02:27:38 24 4
gpt4 key购买 nike

在下面的代码中

tt=5;
for(i=0;i<tt;i++)
{

int c,d,l;
scanf("%lld%lld%lld",&c,&d,&l);
printf("%d %d %d %d",c,d,l,tt);
}

在第一次迭代中,“tt”的值自动变为 0。我知道我已经将 c、d、l 声明为 int 并接受了很长时间的输入,所以它使 c、d=0。但是,我仍然无法理解 tt 是如何变为 0 的。

最佳答案

小但强制性的公告。正如评论中所说,你面临未定义的行为,所以

  • 不要对 tt 被赋值为零感到惊讶
  • 不要对在无关紧要的代码更改后 tt 未分配为零感到惊讶(例如,将初始化从“int i,tt;”重新排序为“int tt, i;”,反之亦然)
  • 在使用不同的标志或不同的编译器版本或针对不同的平台或使用不同的输入进行测试后,对于 tt 未分配为零不要感到惊讶
  • 不要对任何事情感到惊讶。任何行为都是可能的。

您不能期望此代码以某种方式工作,因此永远不要在实际程序中使用它

但是,您似乎对此没有意见,问题是“tt 实际发生了什么”。恕我直言,这个问题真的很棒,它揭示了更深入地理解编程的热情,并且有助于深入研究底层。让我们开始吧。

可能的解释

我未能在 VS2015 上重现行为,但情况很清楚。实际数据对齐、变量大小、字节顺序、堆栈增长方向和其他细节可能因您的 PC 而异,但总体思路应该是相同的。

变量 i, tt, c, d, l 是本地变量,因此它们存储在 stack 上.让我们假设,sizeof(int) 是 4 而 sizeof(long long) 是 8,这是很常见的。然后图中显示了一种可能的数据对齐方式(地址从左到右增长,每个单元格代表一个字节):

enter image description here

当执行scanf 时,您传递c 的地址(下图中的蓝色箭头)以填充数据。但是数据的大小是 8 字节,所以 ctt 的数据都被覆盖了(图中的蓝色单元格)。对于 little-endian表示,你总是将零写入 tt 除非用户输入了非常大的数字,而 c 实际上获取小数字的有效数据。

enter image description here

但是,c中的有效数据在填充d时会以同样的方式被重写,d在填充时也会发生同样的情况>我。所以只有 l 在描述的情况下会得到非零值。简单测试:为 c、d、l 输入大数并检查 tt 是否仍为零。

如何得到准确答案

您可以从汇编代码中得到所有答案。启用反汇编列表(具体步骤取决于工具链:gcc 有 -S 选项,visual studio 在断点时在上下文菜单中有“goto disassembly”项)并分析列表。查看您的 CPU 将要执行的确切指令真的很有帮助。一些调试器允许一条一条地执行指令。所以你需要找出变量在堆栈上是如何对齐的,以及它们究竟是什么时候被覆盖的。分析 scanf 对初学者来说很难,因此您可以从程序的简化版本开始:将 scanf 替换为以下内容(无法测试,但应该可以):

*((long long *)(&c)) = 1; //or any other user specified value
*((long long *)(&d)) = 2;
*((long long *)(&l)) = 3;

关于c++ - 一种独特的数据转换类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41510025/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com