【问题标题】:How to detect in C whether your machine is 32-bits如何在 C 中检测您的机器是否为 32 位
【发布时间】:2012-10-18 01:19:18
【问题描述】:

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


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

B:在第 4 行 1

C:在第 4 行 1

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

__________ 第二个暂定答案:

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

【问题讨论】:

  • 可能你可以从这个问题stackoverflow.com/questions/3319717/…得到一个替代方案@
  • 这是《CS:APP》一书中的一个好问题。第 2 章的内容会很好地为您服务。
  • 这是编译时的事情。编译器、编译器设置和运行编译器的机器将决定 int 的大小,而不是程序运行的机器。

标签: c int


【解决方案1】:

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

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

B:在第 4 行 1

C:在第 4 行 1

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

【讨论】:

  • 如果你说错误在第6行而不在第4行,那么B部分如何导致错误不出现? C部分也是如此
【解决方案2】:

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

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

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

对于 B.

0xffffffff + 1

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

【讨论】:

    【解决方案3】:

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

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

    struct { int x:N; };
    

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

    【讨论】:

      【解决方案4】:

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

      B-

      将第 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);
      }
      

      【讨论】:

        猜你喜欢
        • 2016-02-02
        • 1970-01-01
        • 1970-01-01
        • 2014-07-04
        • 1970-01-01
        • 2012-08-26
        • 2013-10-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多