2

だから私は試験のために改訂しています、そして私はこの問題で立ち往生しました:


2.67◆◆intが32ビットのマシンで実行すると1を生成し、それ以外の場合は0を生成するプロシージャint_size_is_32()を作成するタスクが与えられます。sizeof演算子を使用することは許可されていません。これが最初の試みです:

1 /* The following code does not run properly on some machines */
2 int bad_int_size_is_32() {
3 /* Set most significant bit (msb) of 32-bit machine */
4 int set_msb = 1 << 31;
5 /* Shift past msb of 32-bit word */
6 int beyond_msb = 1 << 32;
7
8 /* set_msb is nonzero when word size >= 32
9 beyond_msb is zero when word size <= 32 */
10 return set_msb && !beyond_msb;
11 }

ただし、32ビットSUNSPARCでコンパイルして実行すると、このプロシージャは0を返します。次のコンパイラメッセージは、問題を示しています。警告:左シフトカウント>=タイプの幅

A.コードはどのようにしてC標準に準拠していませんか?

B.データ型intが少なくとも32ビットであるすべてのマシンで正しく実行されるようにコードを変更します。

C.データ型intが16ビット以上のマシンで正しく実行されるようにコードを変更します。

__ _ __ _ ____私の答え:

A:4行目で31シフトすると、オーバーフローします。符号なし整数標準に従って、表現できる符号なし整数の最大値は2^31-1です。

B:4行目1 << 30

C:4行目1<<14および6行目1<<16

私は正しいですか?そうでなければ、なぜお願いしますか?ありがとうございました!

__ _ __ _ ____ 2番目の暫定的な回答:

B:4行目(1 << 31)>> 1および6行目:int beyond_msb = set_msb + 1; 今回は正しいかもしれないと思います:)

4

4 に答える 4

4

A:4行目で31シフトすると、オーバーフローします。符号なし整数標準に従って、表現できる符号なし整数の最大値は2^31-1です。

エラーは4行目ではなく6行目にあります。コンパイラメッセージは、その理由を正確に説明しています。型のサイズよりも大きいビット数だけシフトすると、未定義の動作になります。

B:4行目1 << 30

C:4行目1<<14および6行目1<<16

これらの変更は両方ともエラーを表示しませんが、関数が誤った結果を出すことにもなります。関数を修正する前に、関数がどのように機能するか(およびどのように機能しないか)を理解する必要があります。

于 2012-10-18T01:24:25.963 に答える
1

まず、30ずつシフトしても、シフトできる最大値はワードサイズw-1であるため、オーバーフローは発生しません。したがって、w = 32の場合、31までシフトできます。

lsbが範囲外の33番目のビットに移動するため、32ビットシフトするとオーバーフローが発生します。

したがって、問題は4行目ではなく6行目にあります。

Bの場合。

0xffffffff + 1

32ビットの場合は0になり、そうでない場合はnozeronoになります。

于 2013-07-28T19:21:03.150 に答える
0

実行時にCで署名された型のサイズをテストする方法は絶対にありません。これは、オーバーフローが未定義の動作であるためです。オーバーフローが発生したかどうかはわかりません。を使用するunsigned intと、結果がゼロになる前に1から始まる値を2倍にできるタイプの数を数えることができます。

実行時ではなくコンパイル時にテストを実行する場合は、次のように機能します。

struct { int x:N; };

ここで、Nは連続して大きい値に置き換えられます。Nコンパイラは、の幅以下である限りプログラムを受け入れ、より大きいint場合は診断/エラーでそれを拒否する必要がありますN

于 2012-10-18T02:18:30.127 に答える
0

左シフトを分割することで、C標準に準拠できるはずです。

B-

Line6を次のように置き換えます

int beyond_msb = (1 << 31) << 1;

C-

4行目を次のように置き換えます

int set_msb = ((1 << 15) << 15) << 1 ;

Line6を次のように置き換えます

int beyond_msb = ((1 << 15) << 15) << 2;

また、質問の拡張として、以下はBとCの両方を満足させ、実行時エラーを安全に保つ必要があります。すべてゼロに戻るまで、一度に少しずつ左にシフトします。

int int_size_is_32() {
//initialise our test integer variable.
int x = 1;  
//count for checking purposes
int count = 0;
//keep shifting left 1 bit until we have got pushed the 1-bit off the left of the value type space.
while ( x != 0 ) {
    x << 1   //shift left
    count++;  
}

return (count==31);
}
于 2014-05-16T01:08:05.300 に答える