C&C++快速入门
4、进制与位
1、课程目标
- 理解不同进制的概念和转换方法
- 掌握二进制与十六进制在编程中的应用
- 理解位(bit)和字节(byte)的关系
- 能够进行进制间的手动转换
2、名词解释
| 术语 | 英文 | 说明 |
|---|---|---|
| 二进制 | Binary | 以2为基数的计数系统,只有0和1 |
| 八进制 | Octal | 以8为基数的计数系统,0-7 |
| 十进制 | Decimal | 以10为基数的日常计数系统,0-9 |
| 十六进制 | Hexadecimal | 以16为基数,0-9和A-F |
| 位 | Bit | 最小的数据单位,0或1 |
| 字节 | Byte | 8个位组成,基本存储单位 |
| 字 | Word | 通常16位(2字节) |
| 双字 | DWORD | 32位(4字节) |
| 四字 | QWORD | 64位(8字节) |
| MSB | Most Significant Bit | 最高有效位 |
| LSB | Least Significant Bit | 最低有效位 |
| 大端序 | Big Endian | 高位字节存储在低地址 |
| 小端序 | Little Endian | 低位字节存储在低地址 |
3、使用工具
| 工具 | 用途 |
|---|---|
| Windows计算器(程序员模式) | 进制转换验证 |
| HxD / 010 Editor | 十六进制编辑器 |
| Python交互式环境 | 快速验证转换 |
4、技术原理
1. 进制基础
十进制 123 = 1×10² + 2×10¹ + 3×10⁰
二进制 1011 = 1×2³ + 0×2² + 1×2¹ + 1×2⁰ = 8+0+2+1 = 11
十六进制 0x1A = 1×16¹ + 10×16⁰ = 16+10 = 26
2. 进制转换表
十进制 二进制 十六进制
0 0000 0x0
1 0001 0x1
2 0010 0x2
3 0011 0x3
4 0100 0x4
5 0101 0x5
6 0110 0x6
7 0111 0x7
8 1000 0x8
9 1001 0x9
10 1010 0xA
11 1011 0xB
12 1100 0xC
13 1101 0xD
14 1110 0xE
15 1111 0xF
3. 内存中的字节序
数值: 0x12345678
大端序 (网络字节序):
地址: 0x00 0x01 0x02 0x03
内容: 0x12 0x34 0x56 0x78
小端序 (x86/x64):
地址: 0x00 0x01 0x02 0x03
内容: 0x78 0x56 0x34 0x12
4、代码实现
1. C语言进制表示与输出
#include <stdio.h>
int main() {
// 不同进制的表示方法
int decimal = 255; // 十进制
int binary = 0b11111111; // 二进制 (C99/GCC扩展)
int octal = 0377; // 八进制 (以0开头)
int hex = 0xFF; // 十六进制 (以0x开头)
printf("=== 进制表示演示 ===\n");
printf("十进制 255:\n");
printf(" 十进制输出: %d\n", decimal);
printf(" 八进制输出: %o\n", decimal);
printf(" 十六进制输出: %x (小写) / %X (大写)\n", decimal, decimal);
// 验证各种表示是否相等
printf("\n=== 验证相等性 ===\n");
printf("decimal=%d, binary=%d, octal=%d, hex=%d\n",
decimal, binary, octal, hex);
return 0;
}
2. 手动实现进制转换
#include <stdio.h>
#include <string.h>
// 十进制转二进制字符串
void DecToBin(int num, char* buffer, int size) {
int i = 0;
char temp[64] = {0};
if (num == 0) {
strcpy(buffer, "0");
return;
}
while (num > 0 && i < 63) {
temp[i++] = (num % 2) + '0';
num /= 2;
}
// 反转字符串
int len = i;
for (int j = 0; j < len && j < size - 1; j++) {
buffer[j] = temp[len - 1 - j];
}
buffer[len < size ? len : size - 1] = '\0';
}
// 二进制字符串转十进制
int BinToDec(const char* binStr) {
int result = 0;
int len = strlen(binStr);
for (int i = 0; i < len; i++) {
result = result * 2 + (binStr[i] - '0');
}
return result;
}
// 十六进制字符串转十进制
int HexToDec(const char* hexStr) {
int result = 0;
int len = strlen(hexStr);
// 跳过0x前缀
int start = 0;
if (len > 2 && hexStr[0] == '0' && (hexStr[1] == 'x' || hexStr[1] == 'X')) {
start = 2;
}
for (int i = start; i < len; i++) {
int digit;
if (hexStr[i] >= '0' && hexStr[i] <= '9') {
digit = hexStr[i] - '0';
} else if (hexStr[i] >= 'A' && hexStr[i] <= 'F') {
digit = hexStr[i] - 'A' + 10;
} else if (hexStr[i] >= 'a' && hexStr[i] <= 'f') {
digit = hexStr[i] - 'a' + 10;
} else {
break;
}
result = result * 16 + digit;
}
return result;
}
int main() {
char binBuffer[64];
// 十进制转二进制
DecToBin(255, binBuffer, sizeof(binBuffer));
printf("255 的二进制: %s\n", binBuffer);
// 二进制转十进制
printf("11111111 的十进制: %d\n", BinToDec("11111111"));
// 十六进制转十进制
printf("0xDEADBEEF 的十进制: %u\n", HexToDec("0xDEADBEEF"));
return 0;
}
3. 查看内存字节序
#include <stdio.h>
void PrintBytes(void* ptr, int size) {
unsigned char* bytes = (unsigned char*)ptr;
printf("内存地址: %p\n", ptr);
for (int i = 0; i < size; i++) {
printf(" 偏移 %d: 0x%02X\n", i, bytes[i]);
}
}
int main() {
unsigned int value = 0x12345678;
printf("=== 字节序检测 ===\n");
printf("值: 0x%08X\n", value);
PrintBytes(&value, sizeof(value));
// 判断字节序
unsigned char* firstByte = (unsigned char*)&value;
if (*firstByte == 0x78) {
printf("\n当前系统: 小端序 (Little Endian)\n");
} else if (*firstByte == 0x12) {
printf("\n当前系统: 大端序 (Big Endian)\n");
}
return 0;
}
4、课后作业
4.1、作业1:进制转换练习
将以下数值转换为其他进制(手算后用程序验证):
- 十进制 1024 → 二进制、十六进制
- 二进制 10101010 → 十进制、十六进制
- 十六进制 0xCAFE → 十进制、二进制
4.2、作业2:实现完整转换工具
编写一个程序,能够:
- 接收用户输入的任意进制数值
- 自动检测输入进制(0x开头为十六进制,0b开头为二进制等)
- 输出该数值的十进制、二进制、八进制、十六进制表示
4.3、作业3:字节序转换函数
实现大端序和小端序的互相转换函数:
unsigned int SwapEndian32(unsigned int value);
unsigned short SwapEndian16(unsigned short value);