C语言二维数组高度获取:main正常,独立函数失效求助
二维数组行列数获取问题的解决方案
问题重现
尝试通过独立函数获取二维数组的行数和列数时,函数返回错误结果,且启用-Werror编译选项时触发指针除法的编译错误。
原代码
#include <stdio.h> int get_height(char **arr) { int i; i = sizeof(arr) / sizeof((char *)arr[0]); return(i); } int get_larger(char **arr) { int i; i = sizeof(arr[0]) / sizeof(char); return(i); } int main() { char arr[4][2] = { {'1', 'C'}, {'E', '5'}, {'2', 'c'}, {'3', 'D'} }; printf("size of arr : %lld\n", sizeof(arr)); int col = sizeof(arr[0]) / sizeof(char); int row = sizeof(arr) / sizeof(arr[0]); printf("size of col : %d\n", col); printf("size of row : %d\n", row); printf("get_height funtion: %d\n", get_height((char **)arr)); printf("get_larger funtion: %d\n", get_larger((char **)arr)); return 0; }
运行结果
> gcc main3.c > .\a.exe size of arr : 8 size of col : 2 size of row : 4 get_height funtion: 1 get_larger funtion: 8
编译错误(启用-Werror)
> gcc -Wall -Wextra -Werror main3.c main3.c: In function 'get_height': main3.c:7:22: error: division 'sizeof (char **) / sizeof (char *)' does not compute the number of array elements [-Werror=sizeof-pointer-div] 7 | i = sizeof(arr) / sizeof((char *)arr[0]); | ^ main3.c:3:23: note: first 'sizeof' operand was declared here 3 | int get_height(char **arr) | ~~~~~~~^~~ main3.c: In function 'get_larger': main3.c:15:25: error: division 'sizeof (char *) / sizeof (char)' does not compute the number of array elements [-Werror=sizeof-pointer-div] 15 | i = sizeof(arr[0]) / sizeof(char); | ^ cc1.exe: all warnings being treated as errors
问题根源
- 数组退化为指针:当二维数组传递给函数时,会自动退化为指向数组首元素的指针。函数参数
char **arr本质是一个指针(64位系统下大小为8字节),而非原数组的整体,因此sizeof(arr)计算的是指针大小,不是数组总大小。 - 类型转换错误:原数组
char arr[4][2]的类型是char (*)[2](指向长度为2的char数组的指针),强制转换为char **是不安全的,两者内存布局完全不同。 - 函数内
sizeof计算无效:get_larger中sizeof(arr[0])实际是指针的大小(8字节),除以sizeof(char)(1字节)得到8,与实际列数2不符。
修复方案
方案1:使用编译期宏(推荐)
宏在预处理阶段展开,能直接获取数组的实际大小,避免数组退化问题:
#include <stdio.h> #define GET_ROWS(arr) (sizeof(arr) / sizeof(arr[0])) #define GET_COLS(arr) (sizeof(arr[0]) / sizeof(arr[0][0])) int main() { char arr[4][2] = { {'1', 'C'}, {'E', '5'}, {'2', 'c'}, {'3', 'D'} }; printf("size of arr : %lld\n", sizeof(arr)); int col = GET_COLS(arr); int row = GET_ROWS(arr); printf("size of col : %d\n", col); printf("size of row : %d\n", row); printf("GET_ROWS macro: %d\n", GET_ROWS(arr)); printf("GET_COLS macro: %d\n", GET_COLS(arr)); return 0; }
方案2:使用固定维度的数组参数
如果二维数组的列数固定,可以将函数参数声明为指向数组的指针,保留维度信息:
#include <stdio.h> // 仅适用于列数为2的char二维数组 int get_rows(char (*arr)[2], size_t total_size) { return total_size / sizeof(arr[0]); } int get_cols(char (*arr)[2]) { return sizeof(arr[0]) / sizeof(char); } int main() { char arr[4][2] = { {'1', 'C'}, {'E', '5'}, {'2', 'c'}, {'3', 'D'} }; printf("size of arr : %lld\n", sizeof(arr)); int col = sizeof(arr[0]) / sizeof(char); int row = sizeof(arr) / sizeof(arr[0]); printf("size of col : %d\n", col); printf("size of row : %d\n", row); printf("get_rows function: %d\n", get_rows(arr, sizeof(arr))); printf("get_cols function: %d\n", get_cols(arr)); return 0; }
方案3:传递行列数参数(灵活适配动态数组)
如果数组是动态分配的,或维度不固定,直接在调用时传入预计算好的行列数:
#include <stdio.h> void print_array(char *arr, int rows, int cols) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { printf("%c ", *(arr + i * cols + j)); } printf("\n"); } } int main() { char arr[4][2] = { {'1', 'C'}, {'E', '5'}, {'2', 'c'}, {'3', 'D'} }; int cols = sizeof(arr[0]) / sizeof(char); int rows = sizeof(arr) / sizeof(arr[0]); printf("size of col : %d\n", cols); printf("size of row : %d\n", rows); print_array((char *)arr, rows, cols); return 0; }
验证结果
以方案1为例,编译运行后输出:
size of arr : 8 size of col : 2 size of row : 4 GET_ROWS macro: 4 GET_COLS macro: 2
使用gcc -Wall -Wextra -Werror编译无错误。
内容的提问来源于stack exchange,提问作者myyou
相关产品推荐
相关产品推荐

