今日C/C++学习笔记20260223
1. 字节序(Endianness)检测
概念
- 大端序:高位字节存储在低地址。
- 小端序:低位字节存储在低地址。
检测代码(利用指针)
c
#include <stdio.h>
int main() {
unsigned int x = 0x12345678;
unsigned char *p = (unsigned char*)&x;
if (*p == 0x78)
printf("小端序\n");
else
printf("大端序\n");
return 0;
}
- 使用
unsigned char*避免符号扩展。 - 若第一个字节为
0x78则为小端,否则为大端(通常0x12)。
2. 宏定义中的括号重要性
错误示例
c
#define AREA(r) PI*r*r
// AREA(1+2) 展开为 PI*1+2*1+2,结果错误
正确写法
c
#define AREA(r) (PI * (r) * (r))
- 每个参数加括号
(r)防止优先级问题。 - 整个表达式加括号
(...)防止外部运算符干扰。
3. 逻辑与(&&) vs 按位与(&)
| 运算符 | 名称 | 返回值 | 短路 | 典型用途 |
|---|---|---|---|---|
&& |
逻辑与 | 0 或 1 | 是 | 条件组合、安全访问 |
& |
按位与 | 整数 | 否 | 位掩码、标志位提取 |
示例
c
int a = 0, b = 1;
if (a && (b = 2)) { } // b 仍为 1(短路)
if (a & (b = 2)) { } // b 变为 2(无短路)
4. 枚举(enum)不能直接输出名称
枚举成员在编译后替换为整数值,运行时无法获取名字。
解决方案:建立映射表
c
enum Color { RED, GREEN, BLUE };
const char* color_names[] = {"RED", "GREEN", "BLUE"};
printf("%s\n", color_names[GREEN]); // 输出 "GREEN"
5. 逻辑运算的短路求值
&&:左为假则右不计算。||:左为真则右不计算。
不影响最终逻辑结果,但可能跳过副作用(赋值、函数调用等)。
6. printf 格式符注意事项
%zu:用于size_t类型(sizeof返回的类型),可移植性好。%lld:用于long long,不应用于size_t(可能类型不匹配)。- 浮点数
%.2f采用四舍五入(向远离零的方向),而非截断或银行家舍入。
7. 数组大小计算
c
int arr[10];
size_t total_bytes = sizeof(arr); // 40
size_t element_count = sizeof(arr) / sizeof(arr[0]); // 10
除数必须是 sizeof(arr[0]),而不是 arr[0](后者是元素值,未初始化时危险)。
8. stdout 与 stderr 的缓冲差异
- stdout:行缓冲(终端),全缓冲(重定向到文件)。
- stderr:无缓冲,每次输出立即写入。
测试程序可通过循环写入大量字符,比较耗时,体会缓冲带来的性能差异。
9. 贪吃蛇游戏优化:消除闪烁
闪烁原因
使用 system("cls") 清屏后再逐字符绘制,屏幕短暂空白造成闪烁。
优化方法:局部刷新
- 只更新变化的部分(蛇头、蛇尾、食物、分数)。
- 使用
gotoxy()定位光标,直接覆盖旧内容。 - 隐藏光标(
hideCursor()),调整控制台窗口大小。
核心代码片段
c
void gotoxy(int x, int y) {
COORD coord = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void move() {
// 计算新头位置,判断是否吃到食物
// 移动身体,记录旧尾部
if (!eat) {
gotoxy(oldTailX, oldTailY);
printf(" "); // 清除旧尾部
} else {
// 更新分数、生成新食物、绘制新食物
}
gotoxy(snakeX[0], snakeY[0]);
printf("■"); // 绘制新头部
}
10. C++ 范围 for 循环(Range-based for)
cpp
int arr[10] = {0};
for (auto b : arr) {
std::cout << b << std::endl; // 输出每个元素
}
- 变量类型需指定或使用
auto。 - 遍历时最好使用
const auto&避免拷贝(若元素类型较大)。
总结
- 熟练掌握指针与类型转换有助于理解内存布局(字节序)。
- 宏定义时务必加括号,避免优先级陷阱。
- 区分逻辑与和按位与,理解短路求值。
- 枚举输出需手动映射。
- 使用正确的格式化输出(
%zu等)提高可移植性。 - 优化控制台程序时,避免频繁清屏,改用局部刷新。
- 利用 C++ 现代特性(如范围 for、auto)简化代码。
注:以上内容基于今日学习对话整理,可作为复习参考。