5

K & R の本を読んでいるのですが、演習の 1 つに対する答えが気になります。

ソリューション マニュアルでは、演習 1-22 で char 配列を宣言しています。

#define MAXCOL 10
char line[MAXCOL];

私の理解では、C配列では0から... n-1になります。その場合、上記の宣言は、0 で始まり 9 で終わる長さ 10 の char 配列にメモリを割り当てる必要があります。サンプル プログラムの関数には、最終的に 10 に等しい整数値 pos が渡され、次の比較が行われます。

int findblnk(int pos) {
while(pos > 0 && line[pos] != ' ')
        --pos;
    if (pos == 0)                   //no blanks in line ?
        return MAXCOL;
    else                        //at least one blank
        return pos+1;               //position after blank
}

pos が 10 で、line[] の長さが 10 しかない場合、line[pos] は配列の範囲外ではありませんか?

C でこのように比較しても問題ないでしょうか?それとも、セグメンテーション違反につながる可能性がありますか? ソリューションマニュアルが正しいと確信しています。これは本当に私を混乱させました。また、必要に応じてプログラム全体を投稿することもできます。ありがとう!

迅速で非常に役立つ回答をありがとう、それは間違いなくバグだと思います。次のブランチを介して呼び出されます。

else if (++pos >= MAXCOL) {
            pos = findblnk(pos);
            printl(pos);
            pos = newpos(pos);
        }

MAXCOL は、前述のように 10 として定義されます。したがって、このブランチの場合、findblnk(pos) pos には最低でも 10 が渡されます。

K & R のソリューション マニュアルは読む価値があると思いますか、それともバグのあるコード例があることで知られていますか?

4

4 に答える 4

3

pos実際にそうである場合10、それは境界外アクセスであり、境界外の配列へのアクセスは未定義の動作であるため、その時点で適切に動作しているように見えるプログラムでさえ何かが起こる可能性があり、結果は信頼できません。ドラフト C99 標準のAnnex J.2 未定義の動作には、次の箇条書きが含まれています。

配列の添字は、オブジェクトが指定された添字で明らかにアクセス可能であっても (宣言 int a[4][5] が与えられた左辺値式 a[1][7] のように) 範囲外です (6.5.6)。

私は手元にK&Rのコピーを持っていませんが、正誤表にはこの問題について何も記載されていません。私の最善の推測は、条件はの<代わりにすべきです>=

于 2013-10-22T02:32:25.240 に答える
2

pos == 9 上記のコードは、その関数に渡される限り問題ありません。pos ==10渡されたときに未定義の動作が発生し、あなたが正しい場合は、回避する必要があります。

ただし、セグメンテーション違反が発生する場合と発生しない場合があります。

于 2013-10-22T02:32:51.240 に答える