C&C++快速入门
5、基础数据类型
1、课程目标
- 掌握C/C++中的基础数据类型
- 理解不同类型的内存占用和取值范围
- 掌握类型转换的规则和陷阱
- 了解Windows API中常用的类型定义
2、名词解释
| 术语 | 英文 | 说明 |
|---|---|---|
| 整型 | Integer | 存储整数的数据类型 |
| 浮点型 | Floating Point | 存储小数的数据类型 |
| 字符型 | Character | 存储单个字符 |
| 布尔型 | Boolean | 存储真/假值 |
| 有符号 | Signed | 可表示正负数 |
| 无符号 | Unsigned | 只能表示非负数 |
| 溢出 | Overflow | 超出类型表示范围 |
| 隐式转换 | Implicit Conversion | 编译器自动进行的类型转换 |
| 显式转换 | Explicit Conversion | 程序员手动指定的类型转换 |
| sizeof | - | 获取类型或变量字节大小的运算符 |
3、Windows API常用类型
| Windows类型 | 对应C类型 | 大小 |
|---|---|---|
| BYTE | unsigned char | 1字节 |
| WORD | unsigned short | 2字节 |
| DWORD | unsigned long | 4字节 |
| QWORD | unsigned __int64 | 8字节 |
| BOOL | int | 4字节 |
| CHAR | char | 1字节 |
| WCHAR | wchar_t | 2字节 |
| LPSTR | char* | 指针 |
| LPWSTR | wchar_t* | 指针 |
| LPVOID | void* | 指针 |
| HANDLE | void* | 指针 |
| SIZE_T | 平台相关 | 4/8字节 |
4、代码实现
1. 基础类型大小与范围
#include <stdio.h>
#include <limits.h>
#include <float.h>
#include <windows.h>
int main() {
printf("=== C语言基础类型 ===\n\n");
// 整型
printf("【整型】\n");
printf("char: %d字节, 范围: %d ~ %d\n",
(int)sizeof(char), CHAR_MIN, CHAR_MAX);
printf("short: %d字节, 范围: %d ~ %d\n",
(int)sizeof(short), SHRT_MIN, SHRT_MAX);
printf("int: %d字节, 范围: %d ~ %d\n",
(int)sizeof(int), INT_MIN, INT_MAX);
printf("long: %d字节, 范围: %ld ~ %ld\n",
(int)sizeof(long), LONG_MIN, LONG_MAX);
printf("long long: %d字节, 范围: %lld ~ %lld\n",
(int)sizeof(long long), 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 long: 范围: 0 ~ %llu\n", ULLONG_MAX);
// 浮点型
printf("\n【浮点型】\n");
printf("float: %d字节, 精度: %d位, 范围: %e ~ %e\n",
(int)sizeof(float), FLT_DIG, FLT_MIN, FLT_MAX);
printf("double: %d字节, 精度: %d位, 范围: %e ~ %e\n",
(int)sizeof(double), DBL_DIG, DBL_MIN, DBL_MAX);
// Windows类型
printf("\n【Windows类型】\n");
printf("BYTE: %d字节\n", (int)sizeof(BYTE));
printf("WORD: %d字节\n", (int)sizeof(WORD));
printf("DWORD: %d字节\n", (int)sizeof(DWORD));
printf("BOOL: %d字节\n", (int)sizeof(BOOL));
printf("LPVOID: %d字节\n", (int)sizeof(LPVOID));
printf("SIZE_T: %d字节\n", (int)sizeof(SIZE_T));
printf("HANDLE: %d字节\n", (int)sizeof(HANDLE));
return 0;
}
2. 类型转换示例
#include <stdio.h>
int main() {
printf("=== 类型转换演示 ===\n\n");
// 1. 整数溢出
printf("【整数溢出】\n");
unsigned char uc = 255;
printf("unsigned char = 255\n");
uc = uc + 1; // 溢出
printf("加1后: %d (溢出回绕到0)\n", uc);
signed char sc = 127;
printf("\nsigned char = 127\n");
sc = sc + 1; // 溢出
printf("加1后: %d (溢出变为负数)\n", sc);
// 2. 有符号与无符号比较陷阱
printf("\n【有符号vs无符号陷阱】\n");
int a = -1;
unsigned int b = 1;
if (a < b) {
printf("-1 < 1 (正确)\n");
} else {
printf("-1 >= 1 (错误!因为-1被转为无符号大数)\n");
}
printf("实际比较: %u vs %u\n", (unsigned int)a, b);
// 3. 浮点精度问题
printf("\n【浮点精度问题】\n");
float f1 = 0.1f;
float f2 = 0.2f;
float f3 = f1 + f2;
printf("0.1 + 0.2 = %.20f (不精确!)\n", f3);
// 正确的浮点比较方式
float epsilon = 0.00001f;
if (f3 - 0.3f < epsilon && 0.3f - f3 < epsilon) {
printf("使用epsilon比较: 0.1 + 0.2 ≈ 0.3\n");
}
// 4. 强制类型转换
printf("\n【强制类型转换】\n");
int intVal = 65;
printf("int值 %d 转为char: '%c'\n", intVal, (char)intVal);
double pi = 3.14159;
printf("double值 %.5f 转为int: %d\n", pi, (int)pi);
return 0;
}
3. 指针与类型大小
#include <stdio.h>
#include <windows.h>
int main() {
printf("=== 指针类型演示 ===\n\n");
// 所有指针大小相同(取决于平台)
printf("【指针大小】\n");
printf("char*: %d字节\n", (int)sizeof(char*));
printf("int*: %d字节\n", (int)sizeof(int*));
printf("double*: %d字节\n", (int)sizeof(double*));
printf("void*: %d字节\n", (int)sizeof(void*));
#ifdef _WIN64
printf("\n当前编译: 64位 (指针8字节)\n");
#else
printf("\n当前编译: 32位 (指针4字节)\n");
#endif
// 指针运算与类型的关系
printf("\n【指针运算】\n");
int arr[5] = {10, 20, 30, 40, 50};
int* p = arr;
printf("数组地址: %p\n", (void*)p);
printf("p+0 = %p, 值 = %d\n", (void*)(p+0), *(p+0));
printf("p+1 = %p, 值 = %d\n", (void*)(p+1), *(p+1));
printf("地址差: %d字节 (=sizeof(int))\n",
(int)((char*)(p+1) - (char*)p));
return 0;
}
4、课后作业
4.1、作业1:类型大小测试
编写程序,打印以下类型在你的系统上的大小:
size_t,ptrdiff_t,intptr_t,uintptr_twchar_t,char16_t,char32_t
4.2、作业2:溢出检测
实现一个安全的加法函数,能够检测整数溢出:
BOOL SafeAdd(int a, int b, int* result);
// 返回TRUE表示成功,FALSE表示溢出
4.3、作业3:类型转换陷阱
解释以下代码的输出结果:
char c = 200;
printf("%d\n", c); // 输出什么?为什么?
unsigned int u = 0;
u = u - 1;
printf("%u\n", u); // 输出什么?为什么?