为何gcc的-Wdiscarded-qualifiers会对这段代码发出警告?
GCC编译qsort比较函数时的const限定符警告问题
在使用qsort对二维数组排序时,我们需要针对数组元素类型编写对应的比较函数回调。给定如下代码场景:
int matrix[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,1,2,3}, }; qsort(matrix, 3, sizeof(int[4]), compare);
由于qsort的每个排序元素是int[4]类型,因此比较函数会收到指向该类型的const void*指针。我们编写的比较函数如下:
int compare (const void* obj1, const void* obj2) { const int (*ptr1)[4] = obj1; const int (*ptr2)[4] = obj2; /* ... */ return 0; }
但使用GCC 12.2(x86)搭配-Wall -Wextra -std=c17 -pedantic-errors编译时,会针对const int (*ptr1)[4] = obj1;行触发如下错误:
error: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
而Clang和ICX使用相同编译选项时无此警告,且最终代码在三款编译器上都能正常运行。
问题原因
这是GCC与Clang/ICX对const void*到数组指针的隐式转换规则判断差异导致的:
const void*的语义是指向不可修改的任意类型数据,const int (*)[4]的语义是指向由const int组成的数组,两者在逻辑上兼容——都禁止通过指针修改原数组内容。- 但GCC在严格模式下(开启
-pedantic-errors)会将这种隐式转换判定为“丢弃const限定符”(实际是对数组指针与void指针转换的严格校验),而Clang则认可这种符合语义的隐式转换。
解决方案
通过显式强制类型转换明确告知编译器转换意图,即可消除GCC的警告/错误:
int compare (const void* obj1, const void* obj2) { const int (*ptr1)[4] = (const int (*)[4])obj1; const int (*ptr2)[4] = (const int (*)[4])obj2; /* ... */ return 0; }
显式转换后,GCC会认可类型转换的合法性,不再触发相关警告。
内容的提问来源于stack exchange,提问作者Lundin
相关产品推荐
相关产品推荐

