2012-01-14 12 views
3

GCCのステートメントエクスプレッションエクステンションについて読みましたが、使用時に予期しない動作が発生しました。GCCステートメントの表現の問題

この例を守ってください:

#include <stdio.h> 

int main(void) 
{ 

    char* res1 = ({ 
         char arr[] ={'h', 'e', '\0'}; // was char *arr[] 
         arr[0] = 'x'; 
         char* ptr = arr; 
         ptr; 
       }); 


    char* res2 = ({ 
         char arr[] ={'h', 'e', '\0'}; // was char *arr[] 
         arr[0] = 'X'; 
         char* ptr = arr; 
         ptr; 
       }); 

    printf ("%s %p\n", res1, res1); 
    printf ("%s %p\n", res2, res2); 

    return 0; 
} 

出力:私はそれに気付い

X 0x7fff93098160 
X 0x7fff93098160 

、第二ブロックの最初のブロック内の変数arrarrが同じメモリアドレスを取ります。

なぜそれが起こっていますか?

答えて

2

両方ともarrの出現は、自動保存期間を持つ配列オブジェクトです。それらはステートメント式内の包含ブロック{ ... }のローカルです。

各ステートメント式は、そのローカル変数のアドレスを取得します。そのアドレスはres1に保存され、res2 and used *after* the end of the block, when the object arr'は存在しなくなりました

これは、ローカル変数のアドレスを返す関数と同じ問題です。変数が存在しなくなり、プログラムの動作が定義されていない場合、アドレスは無効になります。

だからやってはいけません。

+0

申し訳ありませんが、私は間違ったコードをコピーして貼り付けましたが、修正しました。 –

+0

訂正されたコードが問題になっており、ここではもう必要ないので、私は自分の答えを編集しました。 –

+0

保存期間が自動であることを確認するための参考資料はありますか?完全表現の終わりなどはありませんか? [この質問で来た](http://stackoverflow.com/questions/40486940/declare-an-array-in-gcc-statement-expression-and-return-a-pointer-to-it)。 gccの公式のdocページではこれは言わなかった。 –

3

私が理解する限り、ステートメント式で定義される変数の範囲は、ステートメント式そのものです。つまり、res1が初期化されると、配列はすでに有効範囲外であり、ポインタは未割り当てメモリを指しています。 2番目のステートメント式の配列は、同じメモリを占有します。これは、実際には次のコードと大差ありません。

char* res1; 
{ 
    char arr[] ={'h', 'e', '\0'}; 
    arr[0] = 'x'; 
    char* ptr = arr; 
    res1 = ptr; 
} 

char* res2; 
{ 
    char arr[] ={'h', 'e', '\0'}; 
    arr[0] = 'X'; 
    char* ptr = arr; 
    res2 = ptr; 
} 

printf ("%s %p\n", res1, res1); 
printf ("%s %p\n", res2, res2); 
2

両方のアレイは、ステートメントの式にローカルであり、彼らが占めるメモリは、式の終了後に再利用することができます。この場合、です。

これらのポインタの値にアクセスまたは使用する場合は、未定義の動作が呼び出されるため、それらの同等性は重要ではありません。