0

理解できない行動に遭遇しました。2バイトのvalを返すのが楽しみです。4 バイトの var を作成して何らかの処理を行い、変数を返します。私の仮定では、変数は暗黙的に short に変換されます。ただし、fun() の前に (short) を配置しない限り、printf fun は 2^16 より大きい値を出力するため、戻り値は 2 バイトではないようです。何故ですか?

short fun()
{
long var = 2<<20;
return var;
}

printf("%i", fun());
4

3 に答える 3

3

などの可変個引数関数は、オペランドでデフォルト引数昇格printfと呼ばれるものを実行します。特に、より狭い整数( など)は、可変引数関数に渡されると、自動的に に拡張されます。intshortint

これを回避する 1 つの方法は、 「値hを扱っているにもかかわらずint、それが実際にはshort". 次に、出力をフォーマットprintfする前に値を絞り込みます。short例えば:

printf("%hi", fun());
于 2013-10-07T20:32:34.957 に答える
1

ではreturn var;、 の値がvar関数の戻り値の型である に変換されshortます。C 実装では値が の範囲外であるためshort、オーバーフローが発生します。C 仕様では、整数オーバーフローが発生した場合に何が起こるかを定義していません。

それにもかかわらず、動作は少し奇妙です。呼び出しではprintf、多くの C 実装が から 16 ビットのみを使用しfun()、それらを にプロモートしint、 に渡しますprintf。したがって、オーバーフローしても出力は「0」になります。

あなたのケースで起こっている可能性があるのは、コンパイラshortが単にそれを無視し、それが保持されていたプロセッサレジスタに値を残すことによってへの変換を実装することですvar(同じレジスタを使用して関数値を返します)。これは C 標準で許可されていlongます。レジスタ内の値がshortドメイン内にある場合、ビットを変更せずにそのままにしておくと、 として解釈されたときに同じ値が生成されるためshortです。long値がドメイン外にある場合、short何が起こるかは C 標準では定義されていないため、問題ではありません。

次に、レジスタの内容が引数として単純に直接渡さprintfれます。値がドメイン内にある場合は正しい結果が生成され、値がドメイン内にないshort場合はすべてが許可されるため、これも有効です。varshort

于 2013-10-07T21:36:07.573 に答える
1

10short の範囲を超える左シフト 20 で開始し1000000000000000000000、可変引数を取得する関数に渡します (...)

printf (およびその他の可変個引数関数) が値を見ると、それは基本的に単なるメモリの場所であり、書式指定子を使用して元の型にキャストし直します。これが基本的に行っていることのマクロの例です:

#define va_arg(ap,type)     (*(type *)(((ap)+=(((sizeof(type))+(sizeof(int)-1)) \
                            & (~(sizeof(int)-1))))-(((sizeof(type))+ \
                            (sizeof(int)-1)) & (~(sizeof(int)-1)))))

それを short にキャストするフォーマット指定子を追加すると、キャストされた short が表示される可能性があります。それ以外は、fun() を (短く) 続けてください。

于 2013-10-07T20:43:16.823 に答える