gpt4 book ai didi

c - GCC:使用 -Wcast-qual 将 const 指针转换为数组 typedef 的 const 指针会抛出警告

转载 作者:太空狗 更新时间:2023-10-29 15:03:20 27 4
gpt4 key购买 nike

编辑:问题解释得更深入 here (谢谢@Eric Postpischil)。这似乎是 GCC 中的一个错误。

首先,让我从一些上下文开始:我正在编写的代码使用了一个我无法更改的 API,在我无法更改的 GCC 版本上,带有我不允许删除的编译标志,并且当我完成它时,它必须精确地具有零警告或#pragmas。

编辑:也没有 union 。

EDIT2:假设构建系统也使用 -Wall -ansi -pedantic 和阳光下的所有其他警告。我明天会确认 GCC 版本,但我相当确定它不会高于 GCC 7。与此同时,我正在使用 GCC 6.3 进行测试。

EDIT3:我将问题标记为“已回答”。为了完整起见,我在下面添加了更多信息:

我已经检查了正在使用的编译器版本,它不是很好。我们正在使用 Mingw,gcc.exe --version 告诉我它是 GCC 3.4.5。

此外,编译标志包括 wall wextra wcast-qual wpointer-arith wconversion wsign-conversion 以及其他与当前问题无关的标志。

问题

考虑以下代码:

#include "stdio.h"
#include "stdint.h"

typedef uint32_t MyType[4];

const MyType* foo(const uint8_t* a)
{
return (const MyType*) a;
}

void myapi_foo(const MyType* d) {}

int main()
{
uint8_t a[4*sizeof(uint32_t)];

const MyType* b = foo((const uint8_t*) a);

myapi_foo(b);

return 0;
}

使用 GCC 和 -Wcast-qual 标志编译,此代码将抛出以下警告:

warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] return (const MyType*) a;

编辑:澄清一下,错误在这一行:

return (const MyType*) a;

问题原因

我知道问题的根本原因是 typedef 类型 MyType,它实际上是一个数组。遗憾的是,我没有修改此 typedef 的奢侈,也没有修改 API 函数 myapi_foo 及其可疑的参数类型选择。老实说,我真的不明白为什么编译器对这个转换如此不满意,所以非常欢迎澄清。

问题

最干净向编译器指示所有内容都应被视为指向常量数据的指针的方法是什么?

废弃和潜在的解决方案

以下是我找到的一些“解决方案”,但我并不满意:

  • 删除-Wcast-qual 标志。由于代码质量规则,我不能这样做。
  • 添加 #pragma 以关闭围绕该部分代码的警告(如图所示 here )。同样,我也不允许这样做。
  • 将指针转换为整数,然后转换回指针(如 here 所示)return (const MyType*) (uint32_t) a;。它非常粗糙,但使用 uint32_t 作为内存地址在这个项目中有先例,所以我可能不得不将它用作最后的努力。
  • 编辑:@bruno 建议使用 union 来回避问题。这是一个便携且相当优雅的解决方案。但是,上述代码质量规则完全禁止使用 union 。
  • 编辑:@Eric Postpischil 和@M.M 建议使用 (const void*) cast return (const void*) a;,无论 sizeof(MyType *)。遗憾的是,它对目标不起作用。

感谢您的宝贵时间。

最佳答案

这是 GCC bug 81631 . GCC 无法识别转换为 const MyType * 保留 const 限定符。这可能是因为,在这个“指向四个 const uint32_t 数组的指针”中,GCC 执行数组是否为 const 的测试,而不是数组元素是否为 常量

在某些 GCC 版本中,包括 8.2,解决方法是更改​​:

return (const MyType*) a;

到:

return (const void *) a;

可能适用于更多版本的更彻底的更改是使用:

return (const MyType *) (uintptr_t) a;

关于转换和别名的注意事项:

此代码将 a 传递给将其转换为 const MyType * 的函数可能是一个问题:

uint8_t a[4*sizeof(uint32_t)];

const MyType* b = foo((const uint8_t*) a);

在许多 C 实现中,MyTypeuint32_t 的数组,需要四字节对齐,但是 a 只需要一个-字节对齐。根据 C 2018 6.3.2.3 6,如果 a 未针对 MyType 正确对齐,则未定义转换结果。

此外,此代码建议uint_t 数组a 可用作包含四个uint32_t 的数组。这将违反 C 别名规则。您在问题中显示的代码似乎是示例,而不是实际代码,因此我们无法确定,但您应该考虑这一点。

关于c - GCC:使用 -Wcast-qual 将 const 指针转换为数组 typedef 的 const 指针会抛出警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54502385/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com