这是我想要做的事情: -
struct Test
{
int i;
char s;
float f;
};
int main()
{
int sizestruct=sizeof(struct Test);
printf("size of struct=%d\n", sizestruct);
int maxedge;
printf("enter maxedge value");
scanf("%d", &maxedge);
struct Test *sptr1, *sptr2;
sptr1=(struct Test *) 1000;
sptr2=(struct Test *) maxedge;
printf("sptr1=%d, sptr2=%d\n",sptr1, sptr2);
printf("then sptr2-sptr1=%d\n", sptr2-sptr1);
return 0;
}
现在,如果maxedge = 1996(输出为83),我得到的输出就可以了。即使对于1997,1998和1999年的价值观,它也给出了相同的价值。但对于2000年到2007年的价值,垃圾价值来了。从2008年到2011年的数据,产量为84.但从2012年到2019年,产量仍然是垃圾。
现在考虑这个结构:
struct Test {
int i;
char s;
float f;
char s1;
};
对于上面的结构,无论maxedge的值是什么,输出都是正确的。我无法理解为什么上面的代码会出现垃圾值!!
答案 0 :(得分:6)
我已经尝试过您的代码了。它不会打印垃圾,但乍一看它打印的值与其他值不相关。 (83,-1431655682,1431655849,84)
我不确定它为什么会以这种方式运行,但一般来说,未定义的行为会导致意外行为(就像在这种情况下一样)。
如果指针的差异(以字节为单位)不是12的倍数(一个结构的大小),我们看到的情况可能会发生很奇怪的事情。
除以12明显地以一种除以4然后除以3的方式发生,后者以某种方式执行以便在此处发生。
让我们看一下生成的汇编程序输出:
movl 28(%esp), %edx
movl 36(%esp), %eax
subl %eax, %edx
movl %edx, %eax
这是减法。
sarl $2, %eax
imull $-1431655765, %eax, %eax
movl %eax, 4(%esp)
首先,我们除以4然后用值-1431655765进行乘法运算,这是无符号值2863311531的有符号错误表示。
如果我将此值乘以可分数为3且仅考虑低32位的数字,则将数字除以3.这不适用于其他数字,但可能比分割更快。
所以我们看到,如果不满足某些条件,例如将/ 4'数字的可分性再次提高3,就会发生奇怪的事情。但是没关系,因为没有遵循这些条件是未定义的行为。
答案 1 :(得分:3)
指针差异可能会让你感到惊讶。它会考虑你在数组中要求索引,例如由于array[index]
与*(array+index)
相同,因此在p=&(array[index])
然后p - array == index
时会自然转变为sizeof(struct Test)
。
你的结果看起来还是垃圾吗?
那么,也许你可能会考虑比小于{{1}}的偏移,你在索引== i和索引== i + 1之间的某个地方。我怀疑这种行为是在任何地方指定的,所以你可能没想到任何东西。
答案 2 :(得分:1)
减去两个指针同时指向同一个数组元素(或该数组的一个结尾)的指针是未定义的行为。
通常,编译器假定您的代码遵循标准,因此它生成的代码类似于减去地址并除以对象的大小。如果您的代码编译,则工作正常,如果您的代码没有,则可能产生垃圾。