gpt4 book ai didi

使用位移位计算 C 中有符号的长最大值

转载 作者:太空宇宙 更新时间:2023-11-04 00:35:27 25 4
gpt4 key购买 nike

昨天刚开始学习 C,这让我在元旦快要发疯了……尝试使用移位操作打印不同的 int 范围。除了带符号的长最大/最小值外,一切正常。想不通为什么 (1 << 63) - 1返回 -1 ?但是(1 << 64) -1对于 unsigned long long工作正常...

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

void print_range() {
signed char scmax = (1 << 7) - 1;
char c = scmax; // char means signed char!
unsigned char uscmax = (1 << 8) - 1;
char cmin = -(1 << 7);
unsigned char ucmin = 0;
printf("signed char max: %d = %d, unsigned char max: %d = %d\n", scmax, SCHAR_MAX, uscmax, UCHAR_MAX);
printf("signed char min: %d = %d, unsigned char min: %d\n", cmin, CHAR_MIN, ucmin);

// signed int
int imax = (1 << 31) - 1; //(2 << 30) - 1;
unsigned int uimax = (1 << 32) - 1;
int imin = -(1 << 31);
//NOTE: %d is for signed char/short/int, %u is for the unsigned formatter.
printf("signed int max: %d = %d, unsigned int max: %u = %u\n", imax, INT_MAX, uimax, UINT_MAX);
printf("signed int min: %d = %d, unsigned int min = %d\n", imin, INT_MIN, 0);

long long lmax = (1 << 63) - 1L; // WHY DOES THIS NOT WORK???
unsigned long long ulmax = (1 << 64) - 1;
long long lmin = -(1 << 63); // NEITHER DOES THIS???
printf("signed long max: %lld = %lld, unsigned long max: %llu = %llu\n", lmax, LLONG_MAX, ulmax, ULLONG_MAX);
printf("signed long min: %lld = %lld, unsigned long min: %d\n", lmin, LLONG_MIN, 0);
}

最佳答案

请记住,编程语言是一种规范,用英语写在一些技术报告中。它不是一个软件。对于 C11 , 请参阅 n1570

1 这样的文字常量不是 long ,而是一个 int .

编写文字常量 long 1、需要写1L (或者你可以编码 (long)1 ....)。编写文字常量 unsigned long long 1、应该写1ULL (或代码 (unsigned long long)1,这是一个常量表达式)。

文字常数适合“最小”整数类型,大到足以表示它。所以1是一个 int ,以及在 64 位计算机上(实际上,C 的实现就像我的 Linux/x86-64 计算机一样)10000000000 (即 1010)是一个 long (因为它不适合 int ),因为在这样的计算机上 int -s 有 32 位和 long -s 有 64 位。

请注意 int 的大小或范围未由 C99 或 C11 标准精确定义,并且可能因一种实现而异。您可能希望包括 <stdint.h> standard header并使用类似 int32_t 的类型...

所以 1 << 63是一个 (int)1左移 63 位(因为左操作数是 int 移位在 int -s 上运行)。在我的 Linux/x86-64 上,一个 int只有 32 位,所以该操作是一个 undefined behavior .

您应该非常害怕未定义的行为,请参阅 this answer 中的引用资料.可悲的是,偶尔,未定义的行为可能会像您希望的那样工作(但它仍然是 UB)。

查看代码的另一种方式是关注 software portability .


顺便说一句,养成编译所有警告和调试信息的习惯,例如与 gcc -Wall -Wextra -g如果使用 GCC .有时,编译器会很聪明地在这种情况下向您发出警告。然后,改进您的代码以删除所有警告。稍后,使用调试器 ( gdb ) 逐步运行您的代码并了解(通过在调试器中查询程序的状态)发生了什么。


在你的代码中你有:

     char c = scmax; // char means signed char!

遗憾的是,它要棘手得多。你有几种 C 的变体或方言。在某些变体中,char在其他情况下,已签署 char未签名。您拥有的变体是特定于实现的(编译器作者选择最容易在某些目标体系结构上实现的变体)。用GCCC dialect options喜欢-fsigned-char-funsigned-char (你几乎不应该使用它,当你使用它们时,非常要小心后果;你可能需要重新编译你的整个 C 标准库)。

关于使用位移位计算 C 中有符号的长最大值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41418472/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com