【C语言】 整型变量

整型数据概述

整型数据是C语言中最基础的数据类型之一,用于表示整数。整数是不带小数部分的数值,可以是正数、负数或零。在计算机中,整型数据以二进制形式存储,其表示范围和精度由具体的整型类型决定。

整型类型分类

基本整型关键字

C语言提供了多种整型类型,以适应不同的数值范围需求:

1.int(整型)

  • 最常用的整型类型
  • 一般占用4字节(32位系统)
  • C语言标准规定至少占用2字节
  • 数值范围:通常为-2,147,483,648到2,147,483,647

2.short(短整型)

  • 占用空间小于或等于int
  • 一般占用2字节
  • 数值范围:通常为-32,768到32,767

3.long(长整型)

  • 占用空间大于或等于int
  • 一般占用4字节(32位系统)或8字节(64位系统)
  • C语言标准规定至少占用4字节

4.long long(长长整型)

  • C99标准引入
  • 至少占用8字节
  • 数值范围:至少-9,223,372,036,854,775,808到9,223,372,036,854,775,807

示例

c 复制代码
// 各种整型类型示例
#include <stdio.h>

int main() {
    int standard_int = 100;
    short short_int = 200;
    long long_int = 300L;          // L后缀表示long类型
    long long very_long = 400LL;   // LL后缀表示long long类型
    
    printf("int: %d\n", standard_int);
    printf("short: %hd\n", short_int);    // %hd用于short
    printf("long: %ld\n", long_int);      // %ld用于long
    printf("long long: %lld\n", very_long); // %lld用于long long
    
    return 0;
}

有符号与无符号整型

整型可以进一步分为有符号(signed)和无符号(unsigned)两种类型:

有符号整型(signed)

  • 可以表示正数、负数和零
  • signed关键字通常可以省略(默认就是signed)
  • 最高位作为符号位(0表示正数,1表示负数)

无符号整型(unsigned)

  • 只能表示非负数(0和正数)
  • 所有位都用于表示数值大小
  • 相同位数的无符号类型比有符号类型能表示的最大正数大一倍

示例

c 复制代码
#include <stdio.h>
#include <limits.h>

int main() {
    // 有符号整型示例
    signed int signed_num = -100;  // signed可省略
    int another_signed = -50;      // 默认就是signed
    
    // 无符号整型示例
    unsigned int unsigned_num = 200;
    unsigned long big_positive = 4294967295U;  // U后缀表示unsigned
    
    printf("有符号整数: %d\n", signed_num);
    printf("无符号整数: %u\n", unsigned_num);
    printf("无符号长整型最大值: %lu\n", big_positive);
    
    // 查看各种类型的范围
    printf("\n各类型数值范围:\n");
    printf("int范围: %d 到 %d\n", INT_MIN, INT_MAX);
    printf("unsigned int范围: 0 到 %u\n", UINT_MAX);
    printf("short范围: %d 到 %d\n", SHRT_MIN, SHRT_MAX);
    
    return 0;
}

有符号与无符号的区别

特性 有符号整型(signed) 无符号整型(unsigned)
符号位 有(最高位)
可表示负数 可以 不可以
数值范围(32位) − 2 31 -2^{31} −231 到 2 31 − 1 2^{31}-1 231−1 0 到 2 32 − 1 2^{32}-1 232−1
溢出行为 可能产生未定义行为 采用模运算(循环)
默认类型 大多数整型默认有符号 需要显式声明

整型在内存中存储原理

二进制表示与补码系统

计算机内部使用二进制补码形式存储整型数据。补码系统有以下优点:

  • 统一了正数和负数的加减运算
  • 消除了+0和-0的歧义
  • 简化了硬件设计

原码、反码和补码

1.原码 :最高位表示符号,其余位表示绝对值的二进制

2.反码 :正数的反码与原码相同;负数的反码是对原码除符号位外各位取反

3.补码 :正数的补码与原码相同;负数的补码是反码加1

补码计算过程:

  • 正数:原码 = 反码 = 补码
  • 负数:
    1. 先求绝对值的二进制(原码)
    2. 除符号位外各位取反(反码)
    3. 反码加1得到补码
      示例:
c 复制代码
// 补码示例:以8位有符号char类型为例
#include <stdio.h>

void print_binary(char num) {
    for (int i = 7; i >= 0; i--) {
        printf("%d", (num >> i) & 1);
        if (i == 4) printf(" ");  // 添加空格提高可读性
    }
}

int main() {
    char positive = 5;    // 0000 0101
    char negative = -5;   // 1111 1011
    
    printf("+5 的原码/反码/补码: ");
    print_binary(positive);
    printf("\n");
    
    printf("-5 的存储形式(补码): ");
    print_binary(negative);
    printf("\n");
    
    // 验证补码性质
    printf("\n验证补码性质:\n");
    printf("5 + (-5) = %d\n", positive + negative);  // 应该为0
    printf("二进制计算: 00000101 + 11111011 = 00000000\n");
    
    return 0;
}

数值溢出与循环计数

当赋给整型变量的值超出其表示范围时,会发生数值溢出:

无符号整型溢出

无符号整型采用模运算(循环计数):

c 复制代码
#include <stdio.h>

int main() {
    unsigned int max = 4294967295U;  // 32位无符号最大值
    
    printf("无符号整型溢出示例:\n");
    printf("最大值: %u\n", max);
    printf("最大值 + 1: %u\n", max + 1);  // 变为0
    printf("0 - 1: %u\n", 0U - 1);        // 变为最大值
    
    // 计算 -5 在无符号整型中的表示
    unsigned int b = -5;
    printf("\n-5 在无符号整型中: %u\n", b);
    printf("解释: 0 - 5 = 4294967291 (2³² - 5)\n");
    
    return 0;
}

有符号整型溢出

有符号整型溢出是未定义行为(编译器相关):

c 复制代码
#include <stdio.h>
#include <limits.h>

int main() {
    printf("有符号整型溢出(未定义行为):\n");
    int max_int = INT_MAX;
    int min_int = INT_MIN;
    
    printf("INT_MAX: %d\n", max_int);
    printf("INT_MAX + 1: %d (实际行为取决于编译器)\n", max_int + 1);
    
    printf("\nINT_MIN: %d\n", min_int);
    printf("INT_MIN - 1: %d (实际行为取决于编译器)\n", min_int - 1);
    
    return 0;
}

重要提示:在实际编程中,应尽量避免整型溢出,特别是对于有符号整型,因为其溢出行为是未定义的,可能导致不可预测的结果。

输入输出与格式控制符

常用格式控制符

格式控制符 适用类型 说明
%d int 有符号十进制整数
%u unsigned int 无符号十进制整数
%ld long 有符号十进制长整数
%lu unsigned long 无符号十进制长整数
%lld long long 有符号十进制长长整数
%llu unsigned long long 无符号十进制长长整数
%hd short 有符号十进制短整数
%hu unsigned short 无符号十进制短整数
%x, %X 整型 十六进制整数(小写/大写)
%o 整型 八进制整数

输入输出示例

c 复制代码
#include <stdio.h>

int main() {
    int a;
    unsigned int b;
    long c;
    unsigned long d;
    
    // 输入示例
    printf("请输入一个有符号整数: ");
    scanf("%d", &a);
    
    printf("请输入一个无符号整数: ");
    scanf("%u", &b);
    
    printf("请输入一个有符号长整数: ");
    scanf("%ld", &c);
    
    printf("请输入一个无符号长整数: ");
    scanf("%lu", &d);
    
    // 输出示例
    printf("\n输入结果:\n");
    printf("有符号整数: %d\n", a);
    printf("无符号整数: %u\n", b);
    printf("有符号长整数: %ld\n", c);
    printf("无符号长整数: %lu\n", d);
    
    // 不同进制输出
    printf("\n不同进制表示:\n");
    printf("%d 的八进制: %o\n", a, a);
    printf("%d 的十六进制: %x (小写) 或 %X (大写)\n", a, a, a);
    
    // 控制输出宽度和填充
    printf("\n格式化输出:\n");
    printf("默认: %d\n", a);
    printf("宽度10: %10d\n", a);        // 宽度10,右对齐
    printf("宽度10,左对齐: %-10d|\n", a); // 宽度10,左对齐
    printf("宽度10,前导0: %010d\n", a); // 宽度10,前导0填充
    
    return 0;
}

进制转换

十进制转N进制(短除法)

将十进制数转换为N进制数的通用方法:

算法步骤:

  1. 用十进制数除以N,记录余数
  2. 用商继续除以N,记录余数
  3. 重复步骤2,直到商为0
  4. 将余数逆序排列,得到N进制表示

N进制转十进制(按权展开)

将N进制数转换为十进制数的通用方法

算法原理:

确定数据的位数,以及每个位上的数值,规定整数部分的最低位为第0位。

以N为底数,处于第多少位作为指数进行幂运算,然后乘上该位数值,对于每个位重复此操作,最终累加求和,得到转换后的十进制。

C语言中的进制表示

在C语言中,可以直接使用不同进制的字面量:

c 复制代码
#include <stdio.h>

int main() {
    // 十进制(默认)
    int decimal = 3456;
    
    // 八进制(以0开头)
    int octal = 06600;  // 八进制的6600 = 十进制的3456
    
    // 十六进制(以0x或0X开头)
    int hex1 = 0xD80;   // 十六进制的D80
    int hex2 = 0xd80;   // 小写也可以
    
    // 二进制(C语言标准不支持二进制字面量,但有些编译器扩展支持)
    // int binary = 0b11011000000;  // 某些编译器支持
    
    printf("十进制表示: %d\n", decimal);
    printf("八进制表示: %o (十进制值: %d)\n", octal, octal);
    printf("十六进制表示: %x (十进制值: %d)\n", hex1, hex1);
    
    // 使用不同格式输出同一个数
    printf("\n同一数值的不同进制输出:\n");
    printf("十进制: %d\n", decimal);
    printf("八进制: %o\n", decimal);
    printf("十六进制(小写): %x\n", decimal);
    printf("十六进制(大写): %X\n", decimal);
    
    // 显示前缀
    printf("\n带前缀的输出:\n");
    printf("八进制: %#o\n", decimal);   // 输出: 06600
    printf("十六进制: %#x\n", decimal); // 输出: 0xd80
    printf("十六进制(大写): %#X\n", decimal); // 输出: 0XD80
    
    return 0;
}

整型的使用建议

选择合适的类型

c 复制代码
// 根据数据范围选择类型
#include <stdint.h>  // 提供固定宽度整数类型

int main() {
    // 明确范围时使用固定宽度类型
    int8_t small_num = 100;        // 确切占用1字节
    int16_t medium_num = 30000;    // 确切占用2字节
    int32_t large_num = 2000000;   // 确切占用4字节
    int64_t huge_num = 9000000000; // 确切占用8字节
    
    // 无符号固定宽度类型
    uint8_t byte_data = 255;
    uint32_t ip_address = 0xC0A80101;  // 192.168.1.1
    
    return 0;
}

避免有符号和无符号混合运算

c 复制代码
#include <stdio.h>

int main() {
    unsigned int u = 10;
    int s = -5;
    
    printf("有符号与无符号混合运算:\n");
    printf("u + s = %u (可能不是期望的结果)\n", u + s);
    
    // 安全的方法:统一类型后再运算
    if (s < 0) {
        printf("安全方法: s是负数,不能直接与无符号数相加\n");
    } else {
        unsigned int safe_sum = u + (unsigned int)s;
        printf("安全求和: %u\n", safe_sum);
    }
    
    return 0;
}

检查溢出

c 复制代码
#include <stdio.h>
#include <limits.h>

// 安全加法函数
int safe_add(int a, int b) {
    if (b > 0 && a > INT_MAX - b) {
        printf("警告: 加法可能溢出\n");
        return INT_MAX;
    }
    if (b < 0 && a < INT_MIN - b) {
        printf("警告: 加法可能下溢\n");
        return INT_MIN;
    }
    return a + b;
}

int main() {
    int a = INT_MAX - 5;
    int b = 10;
    
    int result = safe_add(a, b);
    printf("%d + %d = %d\n", a, b, result);
    
    return 0;
}
相关推荐
工程师老罗1 小时前
Python中__call__和__init__的区别
开发语言·pytorch·python
JSON_L1 小时前
PHP项目打包为桌面应用
开发语言·php·桌面应用
2301_822366351 小时前
C++中的协程编程
开发语言·c++·算法
m0_736919101 小时前
C++中的事件驱动编程
开发语言·c++·算法
上海合宙LuatOS1 小时前
LuatOS框架的使用(1)
java·开发语言·单片机·嵌入式硬件·物联网·ios·iphone
小程同学>o<1 小时前
嵌入式之C/C++(三)指针
c语言·c++·算法·嵌入式软件·嵌入式面试题库
lxl13071 小时前
学习C++(4)构造函数+析构函数+拷贝构造函数
开发语言·c++·学习
阿kun要赚马内2 小时前
Qt写群聊项目(二):客户端
开发语言·c++·qt
轩情吖2 小时前
数据结构-并查集
开发语言·数据结构·c++·后端··并查集