C语言的整型溢出问题 int、long、long long取值范围 最大最小值

本文详细解析了C语言中的各种数据类型,包括char、short、int、long、long long等的字节数、取值范围及存储机制。通过具体实例说明了如何计算不同类型的最大和最小值,以及正负数的表示方法。

《C和指针》中写过:long与int:标准只规定long不小于int的长度,int不小于short的长度。 double与int类型的存储机制不同,long int的8个字节全部都是数据位,而double是以尾数,底数,指数的形式表示的,类似科学计数法,因此double比int能表示的数据范围更广。 long long在win32中是确实存在,长度为8个字节;定义为LONG64。 为什么会出现long int呢?在win32现在系统中,长度为4;在历史上,或者其他某些系统中,int长度为2,是short int。 即便是long long,在TI的有款平台中,长度为5也就是说,每种类型长度,需要sizeof才知道,如果可能,最好用union看看里面的数据,可以消除一些类型的假象长度。 --------------------- 本文来自 青盏 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/qq_16234613/article/details/77541722?utm_source=copy

类型名称        字节数    取值范围
signed char       1        -128~+127
short int         2        -32768~+32767
int               4        -2147483648~+2147483647
long int          4        -2147483648~+2141483647
long long long int  8      -9223372036854775808~+9223372036854775807

---------------------

本文来自 青盏 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/qq_16234613/article/details/77541722?utm_source=copy 
unsigned int  (unsigned long)
4字节8位可表达位数:2^32=42 9496 7296  
范围:0 ~ 42 9496 7295 (42*10^8)  

int  (long)
4字节8位可表达位数:2^32=42 9496 7296  
范围:-21 4748 3648 ~ 21 4748 3647 (21*10^8)

long long (__int64)
8字节8位可表达位数:2^64=1844 6744 0737 0960 0000  
范围:-922 3372 0368 5477 5808 ~ 922 3372 0368 5477 5807 (922*10^16)

unsigned long (unsigned __int64)
8字节8位可表达位数:2^64=1844 6744 0737 0960 0000  
范围:0 ~ 1844 6744 0737 0955 1615 (1844*10^16)

---------------------

本文来自 青盏 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/qq_16234613/article/details/77541722?utm_source=copy 
在#include<climits>存有各个类型的最大值和最小值
CHAR_MIN       char的最小值
SCHAR_MAX      signed char 最大值
SCHAR_MIN       signed char 最小值
UCHAR_MAX      unsigned char 最大值
SHRT_MAX       short 最大值
SHRT_MIN       short 最小值
USHRT_MAX      unsigned short 最大值
INT_MAX       int 最大值
INT_MIN        int 最小值
UINT_MAX       unsigned int 最大值
UINT_MIN        unsigned int 最小值
LONG_MAX      long最大值
LONG_MIN       long最小值
ULONG_MAX      unsigned long 最大值
FLT_MANT_DIG    float 类型的尾数
FLT_DIG         float 类型的最少有效数字位数
FLT_MIN_10_EXP   带有全部有效数的float类型的负指数的最小值(以10为底)
FLT_MAX_10_EXP    float类型的正指数的最大值(以10为底)
FLT_MIN        保留全部精度的float类型正数最小值
FLT_MAX        float类型正数最大值

---------------------

本文来自 青盏 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/qq_16234613/article/details/77541722?utm_source=copy 

自己推算: 以int类型为例: int为4字节32位,其中首位用0表示正数,用1表示为负数。

因此对于

最大正数可以表示为:0x7fff ffff(7的二进制为0111,f二进制为1111)

最大负数(-1)可以表示为:0xffff ffff 最小负数可以表示为:0x8000 0000(8的二进制为1000)

负数为正数的源码取反码再取补码,过程如下:

1、-1的原码:10000000 00000000 00000000 00000001

2、得反码: 11111111 11111111 11111111 11111110

3、得补码: 11111111 11111111 11111111 11111111

最小负数没有并没有原码和反码表示,最高位为1,其余位为0。就是最小负数。

--------------------- 本文来自 青盏 的优快云 博客 ,全文地址请点击:https://blog.youkuaiyun.com/qq_16234613/article/details/77541722?utm_source=copy

<think>我们正在讨论C语言中各种整型变量的取值范围。根据引用内容,特别是引用[1][3]中关于整形取值范围的讨论,以及引用[2]中关于内存大小的示例,我们可以详细列出各种整型变量的取值范围。 注意:整型取值范围取决于它们所占用的内存大小(以字节为单位)以及是否有符号(signed或unsigned)。此外,C语言标准只规定了最小范围,具体实现可能因编译器和平台而异。但通常在现代系统中,我们有如下常见的大小(引用[2]中的示例在64位Linux系统上运行的结果): - short: 2字节 - int: 4字节 - long: 在64位Linux上是8字节,在Windows上可能是4字节(引用[1]提到过系统差异) 根据引用[3],有符号整型范围计算方式为:最小值是 $-(2^{n-1})$,最大是 $2^{n-1}-1$,其中n是位数(总比特数)。无符号整型范围是0到$2^{n}-1$。 同时,引用[4]提供了格式化输出的方法,例如%hd用于short,%d用于int,%ld用于long,%lld用于long long,%u用于unsigned int等。 因此,我们按照类型列出取值范围(假设使用补码表示有符号整数,这是标准规定的): 1. `char`: - 大小:1字节(8位) - signed char: $-128$ 到 $127$ (即 $-2^7$ 到 $2^7-1$) - unsigned char: $0$ 到 $255$ (即 $0$ 到 $2^8-1$) 2. `short` (或 `short int`): - 大小:2字节(16位) - signed short: $-32768$ 到 $32767$ (即 $-2^{15}$ 到 $2^{15}-1$) - unsigned short: $0$ 到 $65535$ (即 $0$ 到 $2^{16}-1$) 3. `int`: - 大小:通常4字节(32位) - signed int: $-2147483648$ 到 $2147483647$ (即 $-2^{31}$ 到 $2^{31}-1$) - unsigned int: $0$ 到 $4294967295$ (即 $0$ 到 $2^{32}-1$) 4. `long`: - 大小:在32位系统通常是4字节,64位Linux系统中是8字节(引用[2]示例中显示8字节),但在Windows中即使64位也是4字节(注意系统差异) - 因此我们分情况: - 如果为4字节(32位): signed long: $-2147483648$ 到 $2147483647$ (同signed int) unsigned long: $0$ 到 $4294967295$ - 如果为8字节(64位): signed long: $-9223372036854775808$ 到 $9223372036854775807$ (即 $-2^{63}$ 到 $2^{63}-1$) unsigned long: $0$ 到 $18446744073709551615$ (即 $0$ 到 $2^{64}-1$) 5. `long long`: - 大小:通常8字节(64位) - signed long long: $-9223372036854775808$ 到 $9223372036854775807$ - unsigned long long: $0$ 到 $18446744073709551615$ 另外,还有`int8_t`, `int16_t`等固定宽度的整型(来自stdint.h),它们有明确的位数,因此取值范围确定。 注意:在C99标准中引入了`long long`类型,而固定宽度整型需要包含头文件`<stdint.h>`。 为了在代码中打印这些类型的,我们使用引用[4]中提到的格式说明符: - char: %c (字符), 但整数可以用 %hhd (signed char) 或 %hhu (unsigned char) - short: %hd (signed), %hu (unsigned) - int: %d (signed), %u (unsigned) - long: %ld (signed), %lu (unsigned) - long long: %lld (signed), %llu (unsigned) 但是要注意,如果要打印某个类型的最大最小值,可以使用在`<limits.h>`头文件中定义的宏,如`CHAR_MIN`、`CHAR_MAX`、`INT_MAX`等。 下面是一个示例程序(参考引用[2]),演示如何获取大小并打印取值范围: ```c #include <stdio.h> #include <limits.h> int main() { printf("类型大小(字节):\n"); printf("char: %zu\n", sizeof(char)); printf("short: %zu\n", sizeof(short)); printf("int: %zu\n", sizeof(int)); printf("long: %zu\n", sizeof(long)); printf("long long: %zu\n", sizeof(long long)); printf("\n有符号类型取值范围:\n"); printf("signed char: %d 到 %d\n", SCHAR_MIN, SCHAR_MAX); printf("signed short: %d 到 %d\n", SHRT_MIN, SHRT_MAX); printf("signed int: %d 到 %d\n", INT_MIN, INT_MAX); printf("signed long: %ld 到 %ld\n", LONG_MIN, LONG_MAX); printf("signed long long: %lld 到 %lld\n", LLONG_MIN, LLONG_MAX); printf("\n无符号类型取值范围:\n"); printf("unsigned char: 0 到 %u\n", UCHAR_MAX); printf("unsigned short: 0 到 %u\n", USHRT_MAX); printf("unsigned int: 0 到 %u\n", UINT_MAX); printf("unsigned long: 0 到 %lu\n", ULONG_MAX); printf("unsigned long long: 0 到 %llu\n", ULLONG_MAX); return 0; } ``` 注意:`%zu`是用于`sizeof`返回的格式(`size_t`类型)。另外,上面的宏定义在`<limits.h>`中。 最后,由于`long`类型的大小在不同系统上可能不同,编写可移植代码时应注意。 根据以上内容,我们可以总结成表格: | 类型 | 典型大小 | 有符号范围最小值最大) | 无符号范围最小值最大) | |----------------|----------|------------------------------------------------------|----------------------------------------------| | char | 1字节 | $-128$ 到 $127$ | $0$ 到 $255$ | | short | 2字节 | $-32768$ 到 $32767$ | $0$ 到 $65535$ | | int | 4字节 | $-2147483648$ 到 $2147483647$ | $0$ 到 $4294967295$ | | long (Win) | 4字节 | $-2147483648$ 到 $2147483647$ | $0$ 到 $4294967295$ | | long (Linux) | 8字节 | $-9223372036854775808$ 到 $9223372036854775807$ | $0$ 到 $18446744073709551615$ | | long long | 8字节 | $-9223372036854775808$ 到 $9223372036854775807$ | $0$ 到 $18446744073709551615$ | 注意:实际编程中如果不确定`long`的大小,可以使用`sizeof`运算符。 相关问题: §§相关问题§§ 1. 为什么不同平台上`long`类型的大小会有差异? 2. 在C语言中如何使用固定宽度的整型(如`int32_t`)? 3. 如何避免整数溢出问题? 4. 为什么有符号整数的负数范围比正数范围多一个数(例如-128~127)? </think>### C语言整型变量取值范围详解 根据引用内容[1][2][3],C语言整型变量的取值范围取决于**内存大小**和**符号属性**(有符号/无符号)。以下是常见整型的典型取值范围(基于64位Linux系统): #### 一、基本整型取值范围 | 类型 | 内存大小 | 有符号范围最小值最大) | 无符号范围最小值最大) | 格式化输出符 | |----------------|----------|------------------------------------------|----------------------------------|-------------| | `char` | 1字节 | $-128$ → $127$ | $0$ → $255$ | `%c`/`%hhd` | | `short` | 2字节 | $-32,768$ → $32,767$ | $0$ → $65,535$ | `%hd`/`%hu` | | `int` | 4字节 | $-2,147,483,648$ → $2,147,483,647$ | $0$ → $4,294,967,295$ | `%d`/`%u` | | `long` | 8字节 | $-9.2×10^{18}$ → $9.2×10^{18}$ | $0$ → $1.8×10^{19}$ | `%ld`/`%lu` | | `long long` | 8字节 | $-9.2×10^{18}$ → $9.2×10^{18}$ | $0$ → $1.8×10^{19}$ | `%lld`/`%llu` | > 注1:具体范围计算公式($n$=总位数) > - 有符号:$[-2^{n-1}, 2^{n-1}-1]$ > - 无符号:$[0, 2^{n}-1]$ > 例如`short`(16位):有符号范围 $[-2^{15}, 2^{15}-1]$[^3] > 注2:`long`在Windows中通常为4字节(范围同`int`),这是操作系统差异导致的[^1]。 #### 二、取值范围验证代码 参考引用[2],可通过`sizeof`和`<limits.h>`验证: ```c #include <stdio.h> #include <limits.h> int main() { printf("short 大小: %d字节\n", sizeof(short)); printf("有符号short范围: %hd 到 %hd\n", SHRT_MIN, SHRT_MAX); printf("无符号short最大: %hu\n\n", USHRT_MAX); printf("long 大小: %d字节\n", sizeof(long)); printf("有符号long范围: %ld 到 %ld\n", LONG_MIN, LONG_MAX); } ``` #### 三、关键原理说明 1. **有符号整数的存储**:采用**补码**表示(非原码),最高位为符号位[^3] 2. **负数的范围更广**:有符号类型负数范围比正数多1个(如`char`:$-128$比$127$多1) 3. **格式化输出**:必须匹配类型(如`long`用`%ld`),否则输出错误[^4] #### 四、特殊类型说明 - **`_Bool`** (C99):取值 $0$(false)或 $1$(true) - **固定宽度整数**(C11):如`int32_t`(固定4字节),需包含`<stdint.h>`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值