2

所以我正在复习考试,我陷入了这个问题:


2.67 ◆◆ 你的任务是编写一个过程int_size_is_32(),当它在一个int 为32 位的机器上运行时产生1,否则产生0。不允许使用 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 时,我们溢出了,bec 根据无符号整数标准,我们可以表示的最大无符号整数是 2^31-1

B:在第 4 行 1<<30

C:在第 4 行 1<<14 和在第 6 行 1<<16

我对吗?如果不是,为什么?谢谢!

__ _ __ _ ____第二个暂定答案:

B:在第 4 行 (1<<31)>>1 和在第 6 行: int beyond_msb = set_msb+1; 我想这次我可能是对的:)

4

4 回答 4

4

A:当我们在第 4 行移位 31 时,我们溢出了,bec 根据无符号整数标准,我们可以表示的最大无符号整数是 2^31-1

错误出现在第 6 行,而不是第 4 行。编译器消息准确解释了原因:移位大于类型大小的位数是未定义的行为。

B:在第 4 行 1<<30

C:在第 4 行 1<<14 和在第 6 行 1<<16

这两个更改都会导致错误不出现,但也会使函数给出不正确的结果。在修复它之前,您需要了解该功能是如何工作的(以及它是如何不工作的)。

于 2012-10-18T01:24:25.963 回答
1

首先,移位 30 不会产生任何溢出,因为您可以移位的最大值是字长 w-1。因此,当 w = 32 时,您可以移动到 31。

当您将其移动 32 位时会发生溢出,因为 lsb 现在将移动到超出范围的第 33 位。

所以问题出在第 6 行而不是第 4 行。

对于 B。

0xffffffff + 1

如果它是 32 位,则结果为 0,否则为一些 nozero no。

于 2013-07-28T19:21:03.150 回答
0

绝对没有办法在运行时测试 C 中带符号类型的大小。这是因为溢出是未定义的行为;您无法判断是否发生了溢出。如果你使用unsigned int,你可以只计算在结果变为零之前你可以将一个从 1 开始的值加倍的类型。

如果您想在编译时而不是运行时进行测试,这将起作用:

struct { int x:N; };

其中N被连续更大的值替换。只要N不大于 的宽度,编译器就必须接受程序int,并在大于 时以诊断/错误拒绝它N

于 2012-10-18T02:18:30.127 回答
0

您应该能够通过拆分左移来遵守 C 标准。

乙 -

将第 6 行替换为

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

C -

将第 4 行替换为

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

将第 6 行替换为

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 回答