Writing TMin32 in C (P105, second edition) C语言头文件中定义了TMin和TMax的取值: /* * Maximum and minimum values for ints. */   #define INT_MAX 2147483647   #define INT_MIN ( ..

【读书笔记】《Computer System A Programmer's Perspective》Writing TMin32 in C

本贴最后更新于 2443 天前,其中的信息可能已经沧海桑田

Writing TMin32 in C (P105, second edition)


    C语言头文件<limits.h>中定义了TMin和TMax的取值:

       
      /*
      * Maximum and minimum values for ints.
      */
  #define INT_MAX 2147483647
  #define INT_MIN (-INT_MAX-1)
  #define UINT_MAX 0xffffffff
  /* 


   可以看到32位有符号整数取值范围为[-2147483648,2147483647]。书中提到了一个有趣的问题:为什么最小值要写成-2147483647-1(-INT_MAX-1)?为什么不直接写成-2147483648?

   答:由于Tow's Complement正负数的不对称性,直接写成-2147483648可能会导致溢出。在某些编译器中,对于-X的计算,先取数值X再取负数。2147483648超过了32位有符号整数的表示范围,造成了溢出,因此必须写成-2147483647-1。


Errata for
Computer Systems: A Programmer's Perspective (CS:APP)


http://csapp.cs.cmu.edu/public/1e/public/errata.html 


  • p. 60, Problem 2.20:
    • The value -2147483648 should be written -2147483647-1 in entries 1, 2, and 4, and as(-2147483647-1) in entries 3 and 5. See the Note on writing TMin in C for a discussion.
    • 2nd & 3rd entries in table should have -2147483647 rather than -21474836487.
    • 4th & 5th entries in table should have 2147483647 rather than 21474836487.





A Note on TMin



http://csapp.cs.cmu.edu/public/1e/public/tmin.html 

Summary

Due to one of the rules for processing integer constants in ANSI C, the numeric constant -2147483648 is handled in a peculiar way on a 32-bit, two's complement machine.

The problem can be corrected by writing -2147483647-1, rather than -2147483648 in any C code.

Description of Problem

The ANSI C standard requires that an integer constant too large to be represented as a signed integer be ``promoted'' to an unsigned value. When GCC encounters the value 2147483648, it gives a warning message: ``warning: decimal constant is so large that it is unsigned.'' The result is the same as if the value had been written 2147483648U.

The compiler processes an expression of the form -X by first reading the expression X and then negating it. Thus, when the C compiler encounters the constant -2147483648, it first processes 2147483648, yielding 2147483648U, and then negates it. The unsigned negation of this value is also 2147483648U. The bit pattern is correct, but the type is wrong!

Writing TMin in Code

The ANSI C standard states that the maximum and minimum integers should be declared as constants INT_MAX and INT_MIN in the file limits.h. Looking at this file on an IA32 Linux machine (in the directory /usr/include), we find the following declarations:


/* Minimum and maximum values a `signed int' can hold.  */#define INT_MAX2147483647#define INT_MIN(-INT_MAX - 1)

This method of declaring INT_MIN avoids accidental promotion and also avoids any warning messages by the C compiler about integer overflow.

The following are ways to write TMin_32 for a 32-bit machine that give the correct value and type, and don't cause any error messages:

  • -2147483647-1
  • (int) 2147483648U
  • 1<<31
The first method is preferred, since it indicates that the result will be a negative number. 

回帖   
请输入回帖内容...