程序无法将变量识别为 long int 或 unsigned int

Program not recognizing the variable as long int nor as unsigned int

由于有符号整数溢出,我得到的不是数字“2147483648”,而是“-2147483648”。我尝试将变量声明为 long int 和 unsigned int 都没有用。他们只是不被认为是这样的类型。如果有人想知道,我会改变价值。

int multiplier = 1,i;
long int mpy = 0;
for(i=32;i>=0;i--){
mpy = 1 << multiplier++;
printf("mpy = %d\n",mpy);
}

根据您使用的编译器,以及您是在 32 位还是 64 位模式下编译,您所看到的可能与预期完全一样。

https://software.intel.com/en-us/articles/size-of-long-integer-type-on-different-architecture-and-os

tl;dr:对于 MSVC,intlong 都是 32 位的,如果你想存储更大的数字,你需要升级到 __int64。使用 gcc 或其他 32 位模式的编译器,您 运行 会遇到 int = long = 32 位的相同问题,这对您的情况没有帮助。只有当您在非 Microsoft 编译器上转向 64 位编译时,intlong 才会开始出现分歧。

根据评论部分进行编辑: int64_tlong long 也是可以使用的符合标准的类型。或者,unsigned 将允许发布者将其值放入 32 位。

因为常量 1 是一个 int,当向左移动时,它仍然是一个 int。如果您想要 unsigned long long,请将其设为:

unsigned long long mpy = 1ULL << multiplier++;

您可以使用后缀 LULLL 之一代替 longunsigned longlong long(并且这些的小写版本,但后缀最好写成大写以避免 l1 混淆)。选择取决于您真正想做什么。

注意<<的结果类型是左边操作数的类型。移位的结果仅在随后转换为赋值运算符左侧的类型。作业的左轴不影响右轴值的计算方式。

As user3528438 pointed out in a ,正如我假设的(可能是错误的)你会知道——如果 multiplier<< 运算符的 RHS)求值为负值或一个值等于或大于整数类型中的位数,则调用未定义的行为。

请注意,long longunsigned long long 是已有 15 年历史的旧标准 (C99) 和较新的 C11 标准中的标准——但它们不是四分之一世纪的一部分旧 C89/C90 标准。如果您被困在一个编译器处于时间扭曲的平台上——发布日期在 201x 十年,C 标准兼容日期是 1990 年——那么您必须使用替代的特定于平台的 64 位技术。更新问题中的循环涵盖 33 个值,因为您从 32 向下计数并包括 0。没有 32 位类型对于 33 个班次中的每个班次都有不同的值。

(高级用户可能对 INT35-C Use correct integer precisions and N1899 — Integer precision bits update 感兴趣;到目前为止,它们对大多数人来说有点深奥。我不确定我是否会发现有必要担心所提出的问题。 )

另请注意下面评论中关于 printf() 格式的讨论。您应该确保以正确的格式打印该值。对于 long int,应该是 %ld;对于 unsigned long long,那将是 %llu。其他类型需要其他格式。确保您使用的是合理的编译器警告选项。如果您使用的是 GCC,您应该将 gcc -Wall -Wextra -Werror -std=c11 视为一组相当有效的选项;在编译 C 代码时,我使用的选项甚至比那些选项更严格。