程序无法将变量识别为 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,int
和 long
都是 32 位的,如果你想存储更大的数字,你需要升级到 __int64
。使用 gcc 或其他 32 位模式的编译器,您 运行 会遇到 int
= long
= 32 位的相同问题,这对您的情况没有帮助。只有当您在非 Microsoft 编译器上转向 64 位编译时,int
和 long
才会开始出现分歧。
根据评论部分进行编辑:
int64_t
或 long long
也是可以使用的符合标准的类型。或者,unsigned
将允许发布者将其值放入 32 位。
因为常量 1
是一个 int
,当向左移动时,它仍然是一个 int
。如果您想要 unsigned long long
,请将其设为:
unsigned long long mpy = 1ULL << multiplier++;
您可以使用后缀 L
或 UL
或 LL
之一代替 long
、unsigned long
和 long long
(并且这些的小写版本,但后缀最好写成大写以避免 l
和 1
混淆)。选择取决于您真正想做什么。
注意<<
的结果类型是左边操作数的类型。移位的结果仅在随后转换为赋值运算符左侧的类型。作业的左轴不影响右轴值的计算方式。
As user3528438 pointed out in a ,正如我假设的(可能是错误的)你会知道——如果 multiplier
(<<
运算符的 RHS)求值为负值或一个值等于或大于整数类型中的位数,则调用未定义的行为。
请注意,long long
和 unsigned 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 代码时,我使用的选项甚至比那些选项更严格。
由于有符号整数溢出,我得到的不是数字“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,int
和 long
都是 32 位的,如果你想存储更大的数字,你需要升级到 __int64
。使用 gcc 或其他 32 位模式的编译器,您 运行 会遇到 int
= long
= 32 位的相同问题,这对您的情况没有帮助。只有当您在非 Microsoft 编译器上转向 64 位编译时,int
和 long
才会开始出现分歧。
根据评论部分进行编辑:
int64_t
或 long long
也是可以使用的符合标准的类型。或者,unsigned
将允许发布者将其值放入 32 位。
因为常量 1
是一个 int
,当向左移动时,它仍然是一个 int
。如果您想要 unsigned long long
,请将其设为:
unsigned long long mpy = 1ULL << multiplier++;
您可以使用后缀 L
或 UL
或 LL
之一代替 long
、unsigned long
和 long long
(并且这些的小写版本,但后缀最好写成大写以避免 l
和 1
混淆)。选择取决于您真正想做什么。
注意<<
的结果类型是左边操作数的类型。移位的结果仅在随后转换为赋值运算符左侧的类型。作业的左轴不影响右轴值的计算方式。
As user3528438 pointed out in a multiplier
(<<
运算符的 RHS)求值为负值或一个值等于或大于整数类型中的位数,则调用未定义的行为。
请注意,long long
和 unsigned 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 代码时,我使用的选项甚至比那些选项更严格。