C语言整形常量定义

在书中看到这样一道题目: 用预处理指令#define声明一个常数,用以表明一年中有多少秒。书中给的答案是:

#define  SECONDS_PER_YEAR  (60 * 60 * 24 * 365)UL

写一个小程序测试此宏定义,如下:

#include 

#define SECONDS_PER_YEAR (60*60*24*365)UL

int main()
{
    printf("%lu\r\n", SECONDS_PER_YEAR);
    return 0;
}

使用GCC编译时报如下错误: error: ‘SECONDS_PER_YEAR’ undeclared (first use in this function)

查阅一下C99标准(当然,也可以查阅最新的C标准C11,不过我使用的编译器大都是只支持到C99的),在6.4.4节讲到了关于常量的定义,查看其

关于整形常量的定义,如下:

对于十进制整数常量,其定义的形式为:decimal-constant  integer-suffixopt, 在decimal-constant和integer-suffix之间并没有括号。所以,文章

开头提到的书中给出的例题的答案是错误的。下面详细讲解一下有关C语言中整形常量的定义。

在C语言中的整形常量,关于其默认类型,参考C99标准中6.4.4.1节:

The type of an integer constant is the first of the corresponding list in which its value can be represented.

即,C语言中一个十进制整数会被默认为int类型,如果长度超出int表示范围,而又在long int的范围之内,则会被认为是long int类型,如果long int

也表示不了,则会被认为是long long int类型。对于很多在常见的32位系统上编程的人来说可能结尾处加UL的作用并不明显,因为int和long都是32位,

但是对于嵌入式环境编程的人来说,这个就很有必要了,因为程序跑的环境有可能是16位的,且int是16位而long是32位的,这个时候加UL后缀就很有必要了。

对于宏定义:

#define SECONDS_PER_YEAR  60 * 60 * 24 * 365
则60*60*24*365的结果会被认为是一个int,如果是16位的环境则会溢出。如果在结尾加上UL,如下:

#define SECONDS_PER_YEAR  60 * 60 * 24 * 365UL
根据上述C99标准中有关整形常量定义可以知道其实UL首先是与365结合,即365会被认为是一个unsigned long类型的数,而根据C语言算术计算中的类型提升

原则可以知道整个算式的计算结果也会被认为是UL类型的。

对于宏定义:

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
之所以会报错是因为,UL找不到结合的数字,在16位的环境中,先计算60×60×24×365,则会溢出,然后再将这个溢出的值与UL结合,已经没有意义,故编译

会报错。


参考资料:

[1]   C99标准

[2]   http://bbs.21ic.com/icview-196689-1-1.html

[3]   http://blog.csdn.net/ropenyuan/article/details/6157589


你可能感兴趣的:(C语言)