带有 MSVC 与 TCC 的 Bubblesort 程序的意外输出 [英] Unexpected output from Bubblesort program with MSVC vs TCC

查看:13
本文介绍了带有 MSVC 与 TCC 的 Bubblesort 程序的意外输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一个朋友给我发了这个代码,说它没有按预期工作:

One of my friends sent this code to me, saying it doesn't work as expected:

#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 
", sizeOfInput);

    printf("Values before bubble sort are  : 
");
    for ( b = 0; b &lt; sizeOfInput; b++)
        printf("%d
", a[b]);

    printf("End of values before bubble sort... 
");

    for ( outer = sizeOfInput; outer > 0; outer-- )
    {
        for (  inner = 0 ; inner < outer ; inner++)
        {
        printf ( "Comparing positions: %d and %d
",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 :
",sizeOfInput);
        printf ( "Bubble sort sizeOfInput after inner loop is %d :
",sizeOfInput);
    }
    printf ( "Bubble sort total array size at the end is %d :
",sizeOfInput);
    for ( c = 0 ; c < sizeOfInput; c++)
        printf("Element: %d
", a[c]);
}

我正在使用 Micosoft Visual Studio 命令行工具在 Windows XP 机器上编译它. cl/EHsc bubblesort01.c

I am using Micosoft Visual Studio Command Line Tool for compiling this on a Windows XP machine. cl /EHsc bubblesort01.c

我的朋友在恐龙机器上得到了正确的输出(代码是在那里使用 TCC 编译的).
我的输出出乎意料.数组的大小神秘地增长,介于两者之间.

My friend gets the correct output on a dinosaur machine (code is compiled using TCC there).
My output is unexpected. The array mysteriously grows in size, in between.

如果您更改代码,将变量 sizeOfInput 更改为 sizeOfInputt,则会给出预期的结果!

If you change the code so that the variable sizeOfInput is changed to sizeOfInputt, it gives the expected results!

Microsoft Visual C++ 开发人员中心 进行的搜索没有给出sizeOfInput"的任何结果.

A search done at Microsoft Visual C++ Developer Center doesn't give any results for "sizeOfInput".

我不是 C/C++ 专家,很想知道为什么会发生这种情况 - 任何 C/C++ 专家都可以对此有所了解?
无关说明:我认真考虑过在此处发布之前重写整个代码以使用快速排序或合并排序.但是,毕竟不是Stooge那种...

I am not a C/C++ expert, and am curious to find out why this happens - any C/C++ experts who can shed some light on this?
Unrelated note: I seriously thought of rewriting the whole code to use quicksort or merge sort before posting it here. But, after all, it is not Stooge sort...

我知道代码不正确(它读取到最后一个元素之外),但我很好奇为什么变量名会有所不同.

I know the code is not correct (it reads beyond the last element), but I am curious why the variable name makes a difference.

推荐答案

Like 提到了 interjay 的回答,一旦您进入未定义的行为,所有赌注都将关闭.然而,当你说仅仅重命名变量会改变程序的行为时,我很好奇发生了什么(未定义或未定义).

Like interjay's answer mentioned, once you get into undefined behavior all bets are off. However, when you said that merely renaming the variable changed the behavior of the program, I got curious about what was going on (undefined or not).

首先,我不相信重命名变量会改变编译器的输出(所有其他条件都相同),但果然 - 当我尝试它时,我很惊讶地看到您所描述的内容.

First, I didn't believe that renaming the variable would change the compiler's output (all other things being equal), but sure enough - when I tried it, I was surprised to see exactly what you described.

所以我让编译器转储它为源文件的每个版本生成的代码的程序集,并进行比较.以下是我在编译器关于如何布置局部变量的描述中找到的内容:

So I had the compiler dump the assembly for the code it was generating for each version of the source file, and ran a comparison. Here's what I found in the compilers description of how it was laying out the local variables:

    ***** 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
    *****

您会注意到,当变量名为 sizeOfInput 时,编译器会将其放置在比数组 a 更高的地址处(刚好经过数组的末尾)),并且当变量被命名为 sizeOfInputt 时,它会将它放在比数组 a 低的地址,而不是刚好越过数组的末尾.这意味着在具有名为 sizeOfInput 的变量的构建中,当您修改 a[10] 时发生的未定义行为正在改变 sizeOfInput.在使用名称 sizeOfInputt 的构建中,由于该变量不在数组的末尾,对 a[10] 的写入会破坏其他内容.

What you'll notice is that when the variable is named sizeOfInput, he compiler places it at a higher address than array a (just past the end of the array), and when the variable is named sizeOfInputt it places it at a lower address than array a instead of just past the end of the array. That means that in the build that has the variable named sizeOfInput, the undefined behavior that occurs when you modify a[10] is changing the value of sizeOfInput. In the build that uses the name sizeOfInputt, since that variable isn't at the end of the array, the write to a[10] trashes something else.

当一个变量的名称以一种明显无关紧要的方式改变时,为什么编译器会以不同的方式布置变量 - 我不知道.

As to why the compiler would lay out the variables differently when the name of one changes in an apparently insignificant way - I have no idea.

但这是一个很好的例子,说明为什么不应该依赖局部变量(或几乎任何变量,尽管您可以依赖结构元素的布局顺序)的布局,以及为什么在涉及未定义行为时, 它适用于我的机器"并不能证明某些东西有效.

But this is a good example of why you shouldn't count on the layout of local variables (or pretty much any variables, though you can count on the layout order of struct elements), and why when it comes to undefined behavior, "it works on my machine" doesn't cut it as proof that something works.

这篇关于带有 MSVC 与 TCC 的 Bubblesort 程序的意外输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆