5

-O2がこのコードを壊す理由を誰かが理解していますか?さまざまなプラットフォームやさまざまなバージョンのgccで正常に動作するため、gccのバグだと思います。ただし、コードに私が気付いていない特殊性が含まれている可能性もあります。誰かが私を教えてもらえますか?

これがコードです。これは、すべての可能な組み合わせを生成する可変数のネストされたループの実装です。期待される出力は

100 1
010 2
001 4
110 3
101 5

壊れたバージョンのレポート

100 1
010 2
001 4
100 1
010 2

コードは次のとおりです。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main()
{
    int nmax = 5; // finish after 5 combinations
    int n = 3;    // three elements
    int *out = (int*) calloc(nmax, sizeof(int)); 
    int *cnt = (int*) calloc(n, sizeof(int)); // declaring volatile solves the problem. But why ?
    int il, nl, i = 0;
    for (nl=1; nl<=n; nl++)
    {
        for (il=0; il<nl; il++) cnt[il] = 0;
        cnt[nl-1] = -1;
        while ( cnt[0]<n-nl )
        {
            for (il=nl-1; il>=0; il--)
            {
                if ( ++cnt[il] < n-nl+il+1 ) break;
                cnt[il] = 0;
            }
            for (il=1; il<nl; il++)
            {
                if ( cnt[il] <= cnt[il-1] ) cnt[il] = cnt[il-1]+1;
            }
            for (il=0; il<nl; il++) out[i] |= 1<<cnt[il];
            if ( ++i >= nmax ) break;
        }
        if ( i >= nmax ) break;
    }
    for (i=0; i<nmax; i++)
    {
       for (il=0; il<n; il++) printf("%d", out[i]&(1<<il) ? 1 : 0);
       printf("\t%d\n", out[i]);
    }
    free(cnt);
    free(out);
    return 0;
 }
4

1 に答える 1

2

使用している正確な gcc バージョン、ターゲット、および使用している正確なコマンド ラインの詳細を投稿する必要があります。さらに、GCC によって (たとえば、-Sオプションを使用して) 生成されたアセンブリを投稿すると役立ちます。

コンパイラがループ制御式cnt[0]から誤って巻き上げていると思います。while次の変更 (ホイストをシミュレートします) では、誤った出力が生成されます。

// ...

for (nl=1; nl<=n; nl++)
{
    int tmp;                            // <== new line
    for (il=0; il<nl; il++) cnt[il] = 0;
    cnt[nl-1] = -1;
    tmp = cnt[0];                       // <== new line
    while ( /*cnt[0] */ tmp <n-nl )     // modified
    {
        for (il=nl-1; il>=0; il--)

// ...

もちろん、これは推測に過ぎません。要求された詳細を取得して、生成されたコードを調べることができればより興味深いでしょう。

于 2012-10-17T20:00:46.240 に答える