#define值的最大值/最小值

时间:2019-03-03 04:47:50

标签: c types

在C中使用#define命令时,变量可以达到的最大或最小数量是多少?例如,是

#define INT_MIN (pow(-2,31))
#define INT_MAX (pow(2,31))

可接受的定义?我想问一个更好的方法是定义值的数据类型是什么?

3 个答案:

答案 0 :(得分:2)

#define执行令牌替换。如果您不知道标记是什么,则可以将其视为对完整单词的文本替换,就像您的编辑器的“搜索和替换”功能可以做到的那样。因此,

#define FOO 123456789123456789123456789123456789123456789
到目前为止,

是完全有效的-这意味着预处理器将用该长数字替换FOO的每个实例。这样做也是完全合法的(就预处理而言)

#define FOO this is some text that does not make sense

因为预处理器对C一无所知,而只是将FOO替换为定义为C的任何东西。

但这不是您可能正在寻找的答案。

在预处理器替换了宏之后,编译器将必须 compile 任何保留在其位置的内容。而且编译器几乎肯定将无法编译我在此处发布的任何一个示例并出错。

整数常量可以和编译器定义的最大整数类型一样大,它等效于uintmax_t(在<stdint.h>中定义)。例如,如果此类型为64位宽(非常常见),则最大有效整数常量为18446744073709551615615,即2乘以64的幂减去1。

这与该常量的编写或构造方式无关,无论它是通过#define完成,直接写在代码中还是以十六进制编写的,都没有关系。该限制是相同的,因为它是由编译器给定的,并且编译器在预处理完成后运行。

编辑:正如@chux在评论中指出的那样,在最新版本的C(以C99开头)中,默认情况下将对十进制常量进行签名,除非它们带有以其他方式表示的后缀(例如U / {{ 1}},或组合的类型/符号后缀,如u)。在这种情况下,最大有效后缀常量将是ULL值中的任意值(通常是四舍五入的intmax_t最大值的一半);带无符号后缀的常量可以增大到uintmax_t值。 (请注意,带符号或不带符号的C整数常量永远不会为负。)

答案 1 :(得分:0)

#define INT_MIN (pow(-2,31))是不可接受的,因为它形成了错误类型 的最大值。

pow()返回一个double

考虑这一点:INT_MIN % 2导致代码无效,因为%无法在double上完成。

答案 2 :(得分:0)

您的定义不正确的原因有很多:

  • 这些宏名称在标准库头文件 limits.h 中使用,在此处为工具链的目标平台正确定义了它们。

  • 宏不是C语言本身的一部分;而是将替换文本插入代码中,以供编译器评估;因此,您的定义将导致函数pow()在使用这些宏的任何地方被调用-在运行时(重复)进行评估,而不是作为编译时常量。

  • 32位二进制补码整数的最大值不是 2 31 ,而是 2 31 -1 < / em>。

  • pow()函数返回一个double而不是整数-因此您的宏表达式的类型为double

  • 您的宏假定平台的整数大小为32位,而事实并非如此-定义不可移植。可能也是如此,但是整个库是特定于平台的,并且您将在每个平台上使用不同的库/工具链。

如果您必须(并且您实际上不应)为此定义了自己的宏,则应该:

  • 使用不同的宏名称定义它们,
  • 没有关于目标平台整数宽度的假设
  • 使用常量表达式
  • 使用类型为int的表达式。

例如:

#define PLATFORM_INDEPENDENT_INT_MAX ((int)(~0u >> 1u)) 
#define PLATFORM_INDEPENDENT_INT_MIN ((int)~(~0u >> 1u)) 

使用以下代码:

#include <stdio.h>
#include <limits.h>

#define PLATFORM_INDEPENDENT_INT_MAX ((int)(~0u >> 1u)) 
#define PLATFORM_INDEPENDENT_INT_MIN ((int)~(~0u >> 1u)) 
int main()
{
    printf( "Standard: %d\t%d\n", INT_MIN, INT_MAX);
    printf( "Mine:     %d\t%d\n", PLATFORM_INDEPENDENT_INT_MIN, PLATFORM_INDEPENDENT_INT_MAX);

    return 0;
}

输出:

Standard: -2147483648   2147483647                                                                                                                                                 
Mine:     -2147483648   2147483647