- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
编辑:问题解释得更深入 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
及其可疑的参数类型选择。老实说,我真的不明白为什么编译器对这个转换如此不满意,所以非常欢迎澄清。
最干净向编译器指示所有内容都应被视为指向常量数据的指针的方法是什么?
以下是我找到的一些“解决方案”,但我并不满意:
return (const MyType*) (uint32_t) a;
。它非常粗糙,但使用 uint32_t
作为内存地址在这个项目中有先例,所以我可能不得不将它用作最后的努力。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 实现中,MyType
是 uint32_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/
我有一个类型为 const char * 的变量 k,以及一个带有原型(prototype)的 glib 函数 void g_hash_table_replace(GHashTable *hash_t
我收到以下警告: cast between incompatible function types from ‘int (*)(pile *)’ {aka ‘int (*)(struct pile *
我正在阅读 an introduction to gcc其中说: ‘-Wcast-qual’ this option warns about pointers that are cast to rem
所以我有以下最小化的 C11 代码,它定义了一个包含 uint16_t 的结构(这意味着它应该对齐到 2 个字节的结构),我想将一个 char 缓冲区转换为指向该结构的指针。 随着警告全部出现,cla
如果我们有void foo(const char * const ** bar);我们用 char *** bar = malloc(...); 来调用它如foo((const char * cons
对于代码: static const char *a = NULL; abc((char **)&a); abc 方法定义为: abc(char** a) 我收到错误(警告被视为错误): erro
我知道 gcc 有一个选项 -Wcast-align,它会在每次转换指针时发出警告,从而增加目标的对齐要求。 这是我的程序: char data[10]; int ptr = *((int *)dat
编辑:问题解释得更深入 here (谢谢@Eric Postpischil)。这似乎是 GCC 中的一个错误。 首先,让我从一些上下文开始:我正在编写的代码使用了一个我无法更改的 API,在我无法更改
这是我的测试程序: #include #pragma GCC diagnostic ignored "-Wcast-qual" static void proc(char *buf) { p
static char buf[8]; void foo(){ const char* ptr = buf; /* ... */ char* q = (char*)ptr; }
有没有办法让我使用 c++11 关键字 alignas装饰函数get() .在某些情况下,我知道 get() 返回的缓冲区将包含正确对齐的浮点缓冲区。 代码: $ cat c.cxx extern c
我是一名优秀的程序员,十分优秀!