Appearance
C 标准库 - <limits.h>
概述
<limits.h> 头文件定义了各种整数类型的限制值,包括最小值、最大值和位数等信息。这些宏帮助开发者了解整数类型的范围,避免溢出和其他相关问题。
整数类型
C 语言支持多种整数类型:
- char - 字符类型
- signed char - 有符号字符
- unsigned char - 无符号字符
- short - 短整型
- unsigned short - 无符号短整型
- int - 整型
- unsigned int - 无符号整型
- long - 长整型
- unsigned long - 无符号长整型
- long long - 长长整型(C99)
- unsigned long long - 无符号长长整型(C99)
字符类型限制
CHAR_BIT
char 类型的位数(通常为 8)。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("char 位数: %d\n", CHAR_BIT);
return 0;
}CHAR_MIN
char 类型的最小值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("char 最小值: %d\n", CHAR_MIN);
return 0;
}CHAR_MAX
char 类型的最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("char 最大值: %d\n", CHAR_MAX);
return 0;
}SCHAR_MIN, SCHAR_MAX
signed char 类型的最小值和最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("signed char 最小值: %d\n", SCHAR_MIN);
printf("signed char 最大值: %d\n", SCHAR_MAX);
return 0;
}UCHAR_MAX
unsigned char 类型的最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("unsigned char 最大值: %u\n", UCHAR_MAX);
return 0;
}短整型限制
SHRT_MIN, SHRT_MAX
short 类型的最小值和最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("short 最小值: %d\n", SHRT_MIN);
printf("short 最大值: %d\n", SHRT_MAX);
return 0;
}USHRT_MAX
unsigned short 类型的最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("unsigned short 最大值: %u\n", USHRT_MAX);
return 0;
}整型限制
INT_MIN, INT_MAX
int 类型的最小值和最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("int 最小值: %d\n", INT_MIN);
printf("int 最大值: %d\n", INT_MAX);
return 0;
}UINT_MAX
unsigned int 类型的最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("unsigned int 最大值: %u\n", UINT_MAX);
return 0;
}长整型限制
LONG_MIN, LONG_MAX
long 类型的最小值和最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("long 最小值: %ld\n", LONG_MIN);
printf("long 最大值: %ld\n", LONG_MAX);
return 0;
}ULONG_MAX
unsigned long 类型的最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("unsigned long 最大值: %lu\n", ULONG_MAX);
return 0;
}长长整型限制(C99)
LLONG_MIN, LLONG_MAX
long long 类型的最小值和最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("long long 最小值: %lld\n", LLONG_MIN);
printf("long long 最大值: %lld\n", LLONG_MAX);
return 0;
}ULLONG_MAX
unsigned long long 类型的最大值。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("unsigned long long 最大值: %llu\n", ULLONG_MAX);
return 0;
}其他限制
MB_LEN_MAX
多字节字符的最大字节数。
c
#include <stdio.h>
#include <limits.h>
int main() {
printf("多字节字符最大字节数: %d\n", MB_LEN_MAX);
return 0;
}实际应用示例
1. 显示所有整数类型限制
c
#include <stdio.h>
#include <limits.h>
void print_all_limits() {
printf("=== 字符类型 ===\n");
printf("CHAR_BIT: %d\n", CHAR_BIT);
printf("CHAR_MIN: %d\n", CHAR_MIN);
printf("CHAR_MAX: %d\n", CHAR_MAX);
printf("SCHAR_MIN: %d\n", SCHAR_MIN);
printf("SCHAR_MAX: %d\n", SCHAR_MAX);
printf("UCHAR_MAX: %u\n", UCHAR_MAX);
printf("\n");
printf("=== 短整型 ===\n");
printf("SHRT_MIN: %d\n", SHRT_MIN);
printf("SHRT_MAX: %d\n", SHRT_MAX);
printf("USHRT_MAX: %u\n", USHRT_MAX);
printf("\n");
printf("=== 整型 ===\n");
printf("INT_MIN: %d\n", INT_MIN);
printf("INT_MAX: %d\n", INT_MAX);
printf("UINT_MAX: %u\n", UINT_MAX);
printf("\n");
printf("=== 长整型 ===\n");
printf("LONG_MIN: %ld\n", LONG_MIN);
printf("LONG_MAX: %ld\n", LONG_MAX);
printf("ULONG_MAX: %lu\n", ULONG_MAX);
printf("\n");
printf("=== 长长整型 ===\n");
printf("LLONG_MIN: %lld\n", LLONG_MIN);
printf("LLONG_MAX: %lld\n", LLONG_MAX);
printf("ULLONG_MAX: %llu\n", ULLONG_MAX);
printf("\n");
printf("=== 其他 ===\n");
printf("MB_LEN_MAX: %d\n", MB_LEN_MAX);
}
int main() {
print_all_limits();
return 0;
}2. 安全的整数加法
c
#include <stdio.h>
#include <limits.h>
int safe_add(int a, int b) {
if (a > 0 && b > INT_MAX - a) {
printf("警告: 加法溢出\n");
return INT_MAX;
}
if (a < 0 && b < INT_MIN - a) {
printf("警告: 加法下溢\n");
return INT_MIN;
}
return a + b;
}
int main() {
int result1 = safe_add(1000, 2000);
printf("1000 + 2000 = %d\n", result1);
int result2 = safe_add(INT_MAX, 1);
printf("INT_MAX + 1 = %d\n", result2);
return 0;
}3. 安全的整数乘法
c
#include <stdio.h>
#include <limits.h>
int safe_multiply(int a, int b) {
if (a > 0) {
if (b > INT_MAX / a) {
printf("警告: 乘法溢出\n");
return INT_MAX;
}
if (b < INT_MIN / a) {
printf("警告: 乘法下溢\n");
return INT_MIN;
}
} else if (a < 0) {
if (b < INT_MAX / a) {
printf("警告: 乘法溢出\n");
return INT_MAX;
}
if (b > INT_MIN / a) {
printf("警告: 乘法下溢\n");
return INT_MIN;
}
}
return a * b;
}
int main() {
int result1 = safe_multiply(1000, 2000);
printf("1000 * 2000 = %d\n", result1);
int result2 = safe_multiply(INT_MAX, 2);
printf("INT_MAX * 2 = %d\n", result2);
return 0;
}4. 检查整数范围
c
#include <stdio.h>
#include <limits.h>
int is_in_int_range(long value) {
return value >= INT_MIN && value <= INT_MAX;
}
int is_in_unsigned_int_range(long value) {
return value >= 0 && value <= UINT_MAX;
}
int main() {
long values[] = {100, -100, INT_MAX + 1L, INT_MIN - 1L, 0};
int count = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < count; i++) {
long value = values[i];
printf("%ld 在 int 范围内: %d\n", value, is_in_int_range(value));
printf("%ld 在 unsigned int 范围内: %d\n", value, is_in_unsigned_int_range(value));
printf("\n");
}
return 0;
}5. 选择合适的整数类型
c
#include <stdio.h>
#include <limits.h>
const char* get_min_type(long long value) {
if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
return "signed char";
} else if (value >= 0 && value <= UCHAR_MAX) {
return "unsigned char";
} else if (value >= SHRT_MIN && value <= SHRT_MAX) {
return "short";
} else if (value >= 0 && value <= USHRT_MAX) {
return "unsigned short";
} else if (value >= INT_MIN && value <= INT_MAX) {
return "int";
} else if (value >= 0 && value <= UINT_MAX) {
return "unsigned int";
} else if (value >= LONG_MIN && value <= LONG_MAX) {
return "long";
} else if (value >= 0 && value <= ULONG_MAX) {
return "unsigned long";
} else if (value >= LLONG_MIN && value <= LLONG_MAX) {
return "long long";
} else {
return "超出范围";
}
}
int main() {
long long values[] = {10, 1000, 100000, INT_MAX + 1LL, LLONG_MAX};
int count = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < count; i++) {
long long value = values[i];
printf("值 %lld 的最小类型: %s\n", value, get_min_type(value));
}
return 0;
}6. 整数溢出检测
c
#include <stdio.h>
#include <limits.h>
int add_with_overflow_check(int a, int b, int* result) {
if (a > 0 && b > INT_MAX - a) {
return 1;
}
if (a < 0 && b < INT_MIN - a) {
return 1;
}
*result = a + b;
return 0;
}
int multiply_with_overflow_check(int a, int b, int* result) {
if (a > 0) {
if (b > INT_MAX / a) return 1;
if (b < INT_MIN / a) return 1;
} else if (a < 0) {
if (b < INT_MAX / a) return 1;
if (b > INT_MIN / a) return 1;
} else if (a == 0) {
*result = 0;
return 0;
}
*result = a * b;
return 0;
}
int main() {
int result;
if (add_with_overflow_check(INT_MAX, 1, &result)) {
printf("加法溢出\n");
} else {
printf("加法结果: %d\n", result);
}
if (multiply_with_overflow_check(INT_MAX, 2, &result)) {
printf("乘法溢出\n");
} else {
printf("乘法结果: %d\n", result);
}
return 0;
}7. 整数类型大小和范围
c
#include <stdio.h>
#include <limits.h>
void print_type_info(const char* type_name, size_t size,
long long min_value, unsigned long long max_value) {
printf("%-15s 大小: %2zu 字节, 最小值: %20lld, 最大值: %20llu\n",
type_name, size, min_value, max_value);
}
int main() {
printf("=== 整数类型信息 ===\n");
print_type_info("char", sizeof(char), CHAR_MIN, CHAR_MAX);
print_type_info("signed char", sizeof(signed char), SCHAR_MIN, SCHAR_MAX);
print_type_info("unsigned char", sizeof(unsigned char), 0, UCHAR_MAX);
print_type_info("short", sizeof(short), SHRT_MIN, SHRT_MAX);
print_type_info("unsigned short", sizeof(unsigned short), 0, USHRT_MAX);
print_type_info("int", sizeof(int), INT_MIN, INT_MAX);
print_type_info("unsigned int", sizeof(unsigned int), 0, UINT_MAX);
print_type_info("long", sizeof(long), LONG_MIN, LONG_MAX);
print_type_info("unsigned long", sizeof(unsigned long), 0, ULONG_MAX);
print_type_info("long long", sizeof(long long), LLONG_MIN, LLONG_MAX);
print_type_info("unsigned long long", sizeof(unsigned long long), 0, ULLONG_MAX);
return 0;
}整数溢出注意事项
1. 有符号整数溢出
c
#include <stdio.h>
#include <limits.h>
int main() {
int a = INT_MAX;
int b = a + 1;
printf("INT_MAX: %d\n", a);
printf("INT_MAX + 1: %d\n", b);
printf("INT_MIN: %d\n", INT_MIN);
return 0;
}2. 无符号整数溢出
c
#include <stdio.h>
#include <limits.h>
int main() {
unsigned int a = UINT_MAX;
unsigned int b = a + 1;
printf("UINT_MAX: %u\n", a);
printf("UINT_MAX + 1: %u\n", b);
printf("0: %u\n", 0U);
return 0;
}3. 混合运算
c
#include <stdio.h>
#include <limits.h>
int main() {
int a = -1;
unsigned int b = 1;
printf("-1 + 1 (int): %d\n", a + (int)b);
printf("-1 + 1 (unsigned): %u\n", (unsigned)a + b);
return 0;
}总结
<limits.h> 提供的整数限制宏对于编写安全、可靠的程序非常重要。通过了解这些限制,开发者可以:
- 避免整数溢出 - 在进行算术运算前检查是否会溢出
- 选择合适的类型 - 根据数值范围选择最合适的整数类型
- 编写可移植代码 - 使用标准宏而不是硬编码的值
- 理解类型行为 - 了解不同整数类型的范围和特性
记住:
- 有符号整数溢出是未定义行为
- 无符号整数溢出是定义的行为(模运算)
- 使用
<limits.h>中的宏而不是硬编码的值 - 在进行算术运算前检查是否会溢出