GCC:使用-Wcast-qual抛出警告,将const指针转换为数组typedef的const指针 [英] GCC: Casting const pointers to const pointer of array typedef with -Wcast-qual throws warning

查看:339
本文介绍了GCC:使用-Wcast-qual抛出警告,将const指针转换为数组typedef的const指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题在此处进行了更深入的解释(谢谢! @Eric Postpischil).这似乎是GCC中的错误.

problem explained more in depth here (thank you @Eric Postpischil). It seems to be a bug in GCC.

首先,让我从一些上下文开始:我正在编写的代码使用的是我无法更改的API,在我无法更改的GCC版本上,带有不允许删除的编译标志,以及当我完成后,它必须正好为零警告或#pragmas.

First, let me start with some context: the code I'm writing is using an API I can't change, on a GCC version I can't change, with compilation flags I'm not allowed to remove, and when I'm done with it must have precisely zero warnings or #pragmas.

也没有工会.

假定构建系统在阳光下还使用-Wall -ansi -pedantic和其他所有警告. 我明天将确认GCC版本,但我可以肯定它不在GCC 7之上.与此同时,我正在使用GCC 6.3进行测试.

assume the build system also uses -Wall -ansi -pedantic and every other warnings under the sun. I'll confirm the GCC version tomorrow but I'm fairly certain it's not above GCC 7. In the meantime I'm testing with GCC 6.3.

我将此问题标记为已回答".为了完整起见,我在下面添加了更多信息:

I'm marking the issue as 'answered'. For completeness' sake, I'm adding some more information below:

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

I've checked the compiler version being used, and it's not pretty. We're using Mingw and a gcc.exe --version tells me it's GCC 3.4.5.

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

Furthermore, compilation flags include wall wextra wcast-qual wpointer-arith wconversion wsign-conversion along with others that are not relevant to the problem at hand.

考虑以下代码:

#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标志编译后,此代码将引发以下警告:

Compiled with GCC and the -Wcast-qual flag, this code will throw the following warning:

警告:强制转换会从指针目标类型[-Wcast-qual]中丢弃"const"限定词 return(const MyType *)a;

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

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

to clarify, the error is on this line:

return (const MyType*) a;

问题原因

我知道问题的根本原因是typedef类型MyType,它实际上是一个数组.可悲的是,我没有修改这个typedef的奢侈,也没有API函数myapi_foo及其参数类型的可疑选择. 老实说,我不太理解为什么为何编译器对此强制转换不满意,因此澄清起来实在不受欢迎.

The cause of the problem

I know the root cause of the problem is the typedef type MyType which is in fact an array. Sadly, I do not have the luxury of modifying this typedef, nor the API function myapi_foo and its dubious choice of parameter type. To be honest, I don't really understand why is the compiler so unhappy about this cast, so clarifications are more than welcome.

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

What would be the cleanest way of indicating to the compiler everything should be treated as a pointer to const data?

以下是我找到的一些解决方案",但令我不满意:

Here are a few 'solutions' that I have found but left me unsatisfied:

  • 删除 -Wcast-qual 标志.由于代码质量规则,我无法做到这一点.
  • 添加#pragma以关闭该部分代码周围的警告(如此处所示).同样,我不允许这样做.
  • 将指针转换为整数,然后转换回指针(如此处所示)return (const MyType*) (uint32_t) a;. 非常很粗糙,但是在该项目中使用uint32_t作为内存地址是先例,因此我可能不得不将其用作最后的尝试.
  • @bruno建议使用联合来回避问题.这是一个可移植且相当优雅的解决方案.但是,上述代码质量规则完全禁止使用联合.
  • @Eric Postpischil和@ M.M建议使用(const void *)强制转换return (const void*) a;,无论sizeof(MyType*)的值如何,它都可以工作.遗憾的是,它对目标不起作用.
  • Remove the -Wcast-qual flag. I cannot do that due to code quality rules.
  • Add a #pragma to turn off the warning around that part of the code (as shown here). Similarly I'm not allowed to do that.
  • Cast the pointer to an integer, then cast back to a pointer (as shown here) return (const MyType*) (uint32_t) a;. It's very crude, but using uint32_t as memory addresses has precedent in this project so I might have to use it as a last ditch effort.
  • @bruno suggested using an union to side-step the problem. This is a portable and fairly elegant solution. However, the aforementioned code quality rules downright bans the use of unions.
  • @Eric Postpischil and @M.M suggested using a (const void*) cast return (const void*) a;, which would work regardless of the value of sizeof(MyType*). Sadly it doesn't work on the target.

谢谢您的时间.

推荐答案

这是 GCC错误81631 . GCC无法识别对const MyType *的强制类型转换,保留了const限定符.这可能是因为,在此指向四个const uint32_t的数组的指针"中,GCC对数组是否为const进行了测试,以确定数组元素是否为const.

This is GCC bug 81631. GCC fails to recognize the cast to const MyType * retains the const qualifier. This may be because, in this "pointer to array of four const uint32_t", GCC performs a test of whether the array is const whether than of whether the array elements are const.

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

In some GCC versions, including 8.2, a workaround is to change:

return (const MyType*) a;

收件人:

return (const void *) a;

可能会在更多版本中使用的更剧烈的更改是使用:

A more drastic change that is likely to work in more versions is to use:

return (const MyType *) (uintptr_t) a;

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

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

Note About Conversion and Aliasing:

It may be a problem that this code passes a to a function that casts it to const MyType *:

uint8_t a[4*sizeof(uint32_t)];

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

在许多C实现中,作为uint32_t数组的MyType将需要四字节对齐,但是a仅需要一字节对齐.根据C 2018 6.3.2.3 6,如果aMyType的对齐方式不正确,则转换结果未定义.

In many C implementations, MyType, being an array of uint32_t, will require four-byte alignment, but a will only require one-byte alignment. Per C 2018 6.3.2.3 6, if a is not correctly aligned for MyType, the result of the conversion is not defined.

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

Additionally, this code suggests that the uint_t array a may be used as an array of four uint32_t. That would violate C aliasing rules. The code you show in the question appear to be a sample, not the actual code, so we cannot be sure, but you should consider this.

这篇关于GCC:使用-Wcast-qual抛出警告,将const指针转换为数组typedef的const指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆