1

がゼロに初期化された直後にi設定される理由がわかりません。0array

reinitialized value of k私がしなければならないので、プログラムは正常に動作していiます。iしかし、なぜになるのかわかりませんでした0。そして、なぜmemset()配列をクリアしたり、配列をに設定したりするの0ですか?

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{
    long long int i = 123456789;
    long long int j = 987654321;
    long long int cnt = 0;
    int array[9] ;
    int xyz, k, x, rem, se;
    xyz = 0;

 //   printf("I = %llf", i);
    for (i; (i < j) && (cnt < 100000); i++)
    {
        k = i;
        x = 0;
        for (se = 0; se <= 9; se++)
        {
            array[se] = 0;
        }

/*************************************************/

        i = k;   // Here i becomes zero. Why?

/************************************************/

        //memset(array, 0, 9);   

        while(k != 0)
        {
            rem = k % 10;
            for(se = 0; se <= 9; se++)
            {
                if(rem == array[se])
                {
                    xyz = 1;
                    break;
                }

            }
            if(rem == array[se])
                {
                    xyz = 1;
                    break;
                }
            array[x++] = rem;
            k = k / 10;
        }
        if (xyz != 1)
        {
            cnt++;
        //    printf("Cnt = %d  ", cnt);
        //    printf("The value i is = %lld\n", i);
        //    Sleep(10);
        }
        xyz = 0;
        // printf("The value i is = %lld\n", i);
        // printf("Cnt = %d  \n", cnt);
        fflush(stdin);
    }
    printf("The value i is = %lld \n", i-1);
    return 0;
}
4

3 に答える 3

3

バッファ オーバーフローが発生しました。バッファはスタック上にあるため、スタック オーバーフロー†</sup> の一種と見なされる可能性があります。

int array[9];    // Elements array[0] .. array[8]
...

for (se = 0; se <= 9; se++)
{
    array[se] = 0;
}

k余分な 0 で上書きされているに違いありません。iの値であるため、0 が割り当てられますk。ここで行ったように、配列の境界外に書き込むと、「未定義の動作」が呼び出されます。未定義の動作とは、何が起こっても問題ないことを意味します。うまくいくように見えることもあります。場合によっては、予期しない副作用が発生することがあります。「未定義の動作」は絶対に避けてください。

慣用的なforループは次のとおりです。

for (se = 0; se < 9; se++)
    array[se] = 0;

<の代わりに に注意してください<=

†</sup>反対する人もいます。コメントを参照してください。


への(コメントアウトされた)呼び出しについても尋ねますmemset()

//memset(array, 0, 9);

3 番目のパラメータ tomemset()は、設定するメモリ領域のバイト単位のサイズです。配列内の (おそらく) 合計 36 バイトのうち 9 バイトを設定していますが、これは望んでいたものではありません。

ここでは、配列は同じ関数で定義されているため、安全で賢明に記述できます。

memset(array, 0, sizeof(array));

関数arrayにパラメーターが渡された場合、それは正しく機能しません。別のサイズが必要になります。例えば:

void somefunc(int array[], int num)
{
    ...
    memset(array, 0, num * sizeof(array[0]));
    ...
}
于 2012-06-05T10:15:38.600 に答える
2

配列の末尾を上書きしています。

int array[9] ;

for(se = 0; se <= 9; se++)
{
    array[se] = 0;
}

C では、配列は 0 からインデックス付けされるため、ループは 1 ステップ先まで進みます。慣用的な構文は次のとおりです。

for(se = 0; se < 9; se++)

つまり、<要素数を値として使用します。多くの場合、次のように恐ろしい数値定数を削除するために書かれています。

for(se = 0; se < sizeof array / sizeof *array; se++)

これは、sizeof演算子を使用して (コンパイル時に) 適切な要素数を自動的に計算するため、array定義を変更してもループは正しいままです

于 2012-06-05T10:14:52.757 に答える
1

これを確認する 1 つの方法は、&x&array[9]を出力して x と array[9] のポインターを確認することです。

それらが同じ場合は、前述のように確実に上書きしています。

于 2012-06-05T14:02:40.133 に答える