25

Cのsizeof演算子はコンパイル時に解釈され、コンパイル時にコンパイラは配列のサイズとその型を知っているので、sizeofは配列が占めるバイト数を計算できることを読みましたが、次のコードではsizeofはどのように機能しますか?

 #include<stdio.h>
 #include<string.h>
 int main()
 {
    int n;
    scanf("%d",&n);
    int a[n];
    int s=sizeof(a);
    printf("%d",s);
    return 0;
 }

ここで、配列サイズはコンパイル時に不明ですが、どのように正しく機能していますか?

4

6 に答える 6

28

sizeofC89では常にコンパイル時に計算されます。C99および可変長配列なので、可変長配列がsizeofオペランドの式の一部である場合、実行時に計算されます。

オペランドの評価についても同じですsizeof。C89では評価されませんが、C99では、オペランドが可変長配列タイプの場合に評価されます。例えば:

int n = 5;
sizeof (int [n++]); 

// n is now 6
于 2012-04-09T19:08:14.103 に答える
15

sizeofコンパイル時にサイズが完全にはわからない可変長配列に適用するため、コンパイラは実行時にその一部を実行するコードを生成する必要があります。

gcc 4.6.3の高レベルオプティマイザは、表示したコードを次のように変換します

scanf ("%d", &n);
t12 = (long unsigned int) n;
t13 = t12 * 4;
__builtin_alloca (t13);
t16 = (unsigned int) t12;
t17 = t16 * 4;
s18 = (int) t17;
printf ("%d", s18);

それは内部で何が起こっているのかを説明していますか?(一時変数のばかげた数に躊躇しないでください。これは、中間コードのダンプを要求した時点で、プログラムが静的単一代入形式になっていることによるものです。)

于 2012-04-09T19:09:23.687 に答える
8

C99標準から:

6.5.3.4

演算子は、オペランドのサイズ(バイト単位)を生成します。sizeofこれは、式または型の括弧で囲まれた名前の場合があります。サイズは、オペランドのタイプから決定されます。結果は整数です。オペランドの型が可変長配列型の場合、オペランドが評価されます。それ以外の場合、オペランドは評価されず、結果は整数定数になります。

于 2012-04-09T19:11:54.333 に答える
4

その場合、sizeof()は実行時に評価されます。コンパイラは、のサイズが配列宣言時ののa値に基づいていることを知っているため、の適切な値を使用しての適切な値を返すコードを生成します。nnsizeof()

C99では、のすべての使用をsizeof()コンパイル時に完全に評価して、実行時定数に減らすことができるわけではありません。

于 2012-04-09T19:06:15.073 に答える
2

コンパイル時または実行時のどちらsizeofで計算されるか(またはより正式には、その結果が整数定数式であるかどうか)に関係なく、の結果は純粋にその引数sizeofの型に基づいており、可変長配列自体に付随する隠しデータには基づいていません。 。もちろんいつsizeof可変的に変更された型に適用される場合、生成されたプログラムはそのサイズをどこかで追跡する必要があります。ただし、式が十分に単純で、元の長さの派生元の変数を変更できない場合は、単純に再計算する可能性があります。または、型のサイズをどこかに(基本的には非表示のローカル変数に)格納できますが、これはVLAオブジェクトに監視可能な方法で接続されません(たとえば、VLAの最初の要素へのポインターを渡す場合)別の関数への場合、そのポインタを使用してVLAの長さを回復することはできません)。

于 2012-04-09T19:25:14.377 に答える
2

Cのsizeof演算子はコンパイル時に解釈されることを読みました

sizeofVLAを除くすべての場合で、コンパイル時に決定されます。VLAの場合、sizeof実行時に評価されます。

于 2012-04-09T19:08:06.227 に答える