C语言扫雷程序中如何正确索引堆分配的矩阵?
优化扫雷游戏的棋盘索引方法
首先你当前的GET_LOC宏存在两个核心错误:
- 数组下标是元素个数,不是字节数,
gameboard是box_t*类型,gameboard[n]会自动按box_t的大小计算内存偏移,不需要手动乘sizeof(box_t) - 二维转一维的索引公式错误,正确计算应该是
行号 × 列数 + 列号,而非你写的字节偏移叠加
下面是几种更优、更安全的索引方案:
方案1:修复宏定义(最简方案)
修正后的宏会正确计算一维数组中的元素索引,同时添加括号避免运算符优先级问题:
// 注意cols需要是全局变量或宏定义的常量 #define GET_LOC(ROW, COL) gameboard[(ROW) * cols + (COL)] // 使用方式: box_t *loc = &GET_LOC(somerow, somecol);
方案2:使用内联函数(类型安全)
用内联函数替代宏,能获得编译器的类型检查,避免宏的潜在陷阱,还可加入边界校验:
#include <stdint.h> #include <assert.h> // 假设rows和cols是全局变量 static inline box_t* get_loc(int32_t row, int32_t col) { // 边界检查,越界时触发断言(开发阶段)或返回NULL(生产阶段) assert(row >= 0 && row < rows && col >=0 && col < cols); return &gameboard[row * cols + col]; } // 使用方式: box_t *loc = get_loc(somerow, somecol);
方案3:模拟二维数组(直观易用)
如果想直接使用gameboard[row][col]的二维下标语法,可以通过分配二级指针实现,同时保持内存连续(避免碎片化):
// 重新定义全局变量为二级指针 box_t **gameboard = NULL; // 内存分配 gameboard = malloc(rows * sizeof(box_t*)); if (!gameboard) { /* 内存分配失败的错误处理 */ } gameboard[0] = malloc(rows * cols * sizeof(box_t)); if (!gameboard[0]) { /* 内存分配失败的错误处理 */ } // 给每行指针赋值,指向连续内存的对应位置 for (int i = 1; i < rows; i++) { gameboard[i] = gameboard[i-1] + cols; } // 使用方式:直接用二维下标访问 box_t *loc = &gameboard[somerow][somecol]; // 内存释放(注意顺序) free(gameboard[0]); free(gameboard); gameboard = NULL;
额外建议
- 尽量避免使用全局变量,可将
gameboard、rows、cols封装到一个结构体中,作为参数传递给相关函数,提升代码的可维护性 - 所有内存分配后都要检查是否成功,避免空指针访问
内容的提问来源于stack exchange,提问作者raging-loon
相关产品推荐
相关产品推荐

