GCC对const限定符的警告是否正确?

5
考虑以下代码,这是从这个问题中提出来的:
const int (*foo(const char *a))[1]
    { return (const int (*)[1]) a; }

当使用-Wcast-qual编译GCC 8.2(以及旧版本)时,GCC会发出警告:

source>:2:15: 警告:从指针目标类型中丢弃'const'限定符 [-Wcast-qual]
      { return (const int (*)[1]) a; }
               ^

这个警告正确吗?显然,目标类型中有一个const限定符。

它在元素类型上而不是指针直接指向的东西上,即数组类型。但是,即使我们使用typedef int T [1];并将转换替换为(const T *),警告仍然存在。此外,根据C 2018 6.7.3 10,数组类型上的限定符应用于元素类型,而不是数组类型,因此两种方法的类型相同。

Clang没有显示此警告。

如果我们将转换更改为(const void *)

const int (*foo(const char *a))[1]
    { return (const void *) a; }

当我们添加-pedantic到编译开关时,警告消失了。如果我们将其添加,则会得到一个有关const的不同警告:
source>:2:15: warning: return discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
      { return (const void *) a; }
               ^~~~~~~~~~~~~~~~
这看起来像是相同的警告,只是它是关于从返回表达式到函数返回类型的隐含转换,而先前的警告则是关于强制转换中的显式转换。但是,这个警告仅在使用-pedantic时出现。为什么?

1
纯属猜测:你在问题中提到的“数组类型上的限定符适用于元素类型”可能是解决问题的关键。GCC可能会将“指向(const char)的指针”视为“指向(const int)数组的指针”,看到被指向的东西不是const,就发出警告(实际上,如果它愿意再深入一层,它仍然是const)。 - zneak
1
注意:从指向char的指针更改为int会引发对齐问题。 - chux - Reinstate Monica
2
如果您想要测试我的假设,那么在gcc/c/c-typeck.c的handle_warn_cast_qual中会生成此警告,在两行代码中,它们说discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype) & ~TYPE_QUALS_NO_ADDR_SPACE (in_type));。您需要深入了解in_otype,以查看它是否为数组类型,并且元素类型是否设置了其base.readonly_flag位。 - zneak
4
дҪҝз”Ё(int (*)[1])(const int(*)[1])42;жҲ–иҖ…typedef int T[1]; (T*)(const T*)42;еҸҜд»Ҙж¶ҲйҷӨconstе…ій”®еӯ—пјҢеңЁgccе’Ңclangзј–иҜ‘еҷЁдёҠйғҪжІЎжңүиӯҰе‘ҠгҖӮ - KamilCuk
稍微简单一些的代码,但会产生相同的错误:int main(void) { const char *a = 0; (const int (*)[1])(a); } - M.M
显示剩余6条评论
1个回答

4

这是GCC bug 81631。GCC无法识别将指针转换为数组并保留const限定符的问题,因为应用于数组的限定符实际上适用于数组元素,导致复杂性增加。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接