crn*_*nlx 11 c visual-studio-2008
我的一个朋友把这个代码发给了我,说它没有按预期工作:
#include<stdio.h>
void main()
{
int a [10] ={23, 100, 20, 30, 25, 45, 40, 55, 43, 42};
int sizeOfInput = sizeof(a)/sizeof(int);
int b, outer, inner, c;
printf("Size is : %d \n", sizeOfInput);
printf("Values before bubble sort are : \n");
for ( b = 0; b < sizeOfInput; b++)
printf("%d\n", a[b]);
printf("End of values before bubble sort... \n");
for ( outer = sizeOfInput; outer > 0; outer-- )
{
for ( inner = 0 ; inner < outer ; inner++)
{
printf ( "Comparing positions: %d and %d\n",inner,inner+1);
if ( a[inner] > a[inner + 1] )
{
int tmp = a[inner];
a[inner] = a [inner+1];
a[inner+1] = tmp;
}
}
printf ( "Bubble sort total array size after inner loop is %d :\n",sizeOfInput);
printf ( "Bubble sort sizeOfInput after inner loop is %d :\n",sizeOfInput);
}
printf ( "Bubble sort total array size at the end is %d :\n",sizeOfInput);
for ( c = 0 ; c < sizeOfInput; c++)
printf("Element: %d\n", a[c]);
}
Run Code Online (Sandbox Code Playgroud)
我正在使用Micosoft Visual Studio命令行工具在Windows XP计算机上进行编译.
cl /EHsc bubblesort01.c
我的朋友在恐龙机器上获得了正确的输出(代码是使用TCC编译的).
我的输出是意外的.阵列之间神秘地增长.
如果更改代码以便将变量sizeOfInput更改为sizeOfInputt,则会给出预期结果!
在Microsoft Visual C++开发人员中心进行的搜索不会为"sizeOfInput"提供任何结果.
我不是C/C++专家,很想知道为什么会发生这种情况 - 任何C/C++专家谁可以对此有所了解?
无关的注意事项:我认真考虑重写整个代码,以便在发布之前使用quicksort或merge sort.但是,毕竟,它不是Stooge排序......
编辑:我知道代码不正确(它读取超出最后一个元素),但我很好奇为什么变量名称有所不同.
Mic*_*urr 28
就像interjay提到的答案一样,一旦你进入未定义的行为,所有的赌注都会被取消.但是,当你说只是重命名变量改变了程序的行为时,我对正在发生的事情感到好奇(未定义与否).
首先,我不相信重命名变量会改变编译器的输出(所有其他条件相同),但果然 - 当我尝试它时,我很惊讶地看到你所描述的确切内容.
所以我让编译器为每个源文件版本生成的代码转储程序集,然后进行比较.这是我在编译器描述中如何布局局部变量的内容:
***** test.sizeOfInput.cod
_c$ = -56 ; size = 4
_b$ = -52 ; size = 4
_inner$ = -48 ; size = 4
_a$ = -44 ; size = 40
>>> _sizeOfInput$ = -4 ; size = 4
_main PROC
***** test.sizeOfInputt.cod
_c$ = -56 ; size = 4
>>> _sizeOfInputt$ = -52 ; size = 4
_b$ = -48 ; size = 4
_inner$ = -44 ; size = 4
_a$ = -40 ; size = 40
_main PROC
*****
Run Code Online (Sandbox Code Playgroud)
你会注意到的是,当变量命名sizeOfInput,他在更高的地址编译器将它比阵列a(刚刚过去的数组的结束),并且当变量被命名为sizeOfInputt它把它在一个较低的地址比阵列a代替刚刚结束数组.这意味着在具有名为变量的构建中,sizeOfInput修改时发生的未定义行为a[10]是更改值sizeOfInput.在使用该名称的构建中sizeOfInputt,由于该变量不在数组的末尾,因此写入会a[10]破坏其他内容.
至于为什么编译器会以一种显然微不足道的方式改变变量的方式来区分变量 - 我不知道.
但这是一个很好的例子,为什么你不应该依赖局部变量的布局(或几乎任何变量,尽管你可以依赖于struct元素的布局顺序),以及为什么当涉及到未定义的行为时,"它在我的机器上工作"并没有把它作为证明某些东西起作用.
您的代码读取超过数组的末尾.最大值outer为10,最大值inner为9,因此a[inner+1]将读取a[10].这将为您提供未定义的行为,这解释了为什么不同的编译器会给出不同的结果.
至于变量名称有所不同:它可能没有.如果您运行相同的代码两次(使用相同的变量名称),则可能会得到不同的结果.基本上,在调用未定义的行为时,您无法确定程序将执行的任何操作,因此最好不要尝试在变量名等内容中查找含义.
变量名也有可能产生影响.这取决于编译器的实现:例如,使用不同的变量名可能会使编译器以某种方式组织内存,这可能导致程序不同.我认为如果更改变量名称,大多数编译器会输出相同的代码,所以这可能只是运气问题.