gcc 在C++中将常量指针强制转换为void *

klr1opcd  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(285)

下面的代码不能用gcc 10.2.1编译:

  1. struct Bar {
  2. unsigned char *m_a;
  3. unsigned char m_b[1];
  4. };
  5. int main()
  6. {
  7. Bar bar;
  8. const Bar &b = bar;
  9. void *p1 = b.m_a; // Ok
  10. void *p2 = b.m_b; // Error
  11. return 0;
  12. }

编译器错误为:
错误:从'const void*'到'void*'的转换无效[-fpermissive]
我可以通过使用void *p2 = (void *)b.m_b;void *p2 = const_cast<unsigned char *>(b.m_b);来修复这个问题,但是,编译器似乎没有对成员的常量进行相同的处理。
我猜有一个“额外的检查”的数组,而不是与指针,但为什么呢?

  • 谢谢-谢谢
oiopk7p5

oiopk7p51#

拥有const结构会将const加入所有成员。
const加到unsigned char *得到unsigned char * const(也就是说,指针不能改变为指向其他任何东西,但可以改变所指向的值)。这可以被强制转换为void *,因为它也是指向非const的指针。
constunsigned char[1]相加得到const unsigned char[1]Tconst数组实际上是const T的数组)。这可以衰减为const unsigned char *指针,该指针可以强制转换为const void *,而不是void *,因为数组的元素不能被修改,这与指向的对象的第一个成员不同。

nwlqm0z1

nwlqm0z12#

  1. b.m_a

这是一个unsigned char *。它很高兴被转换为void *

  1. b.m_b

这是一个const unsigned char *,这就是数组在C和C++中的工作方式:数组的名字会变成一个指针指向数组中的第一个值。这个数组是const,所以它变成了const unsigned char *,你不能把它转换成void *
请注意,如果您尝试将&b.m_a转换为void *,也会得到相同的错误。
b.m_a本身是const,但它并不指向const对象。这是两件非常不同的事情:const指针和指向const的指针。

tcomlyy6

tcomlyy63#

表达式b的类型为const Bar,这意味着数据成员m_aunsigned char *constm_bconst unsigned char [1]
现在,需要注意的重要事项是that
指向任何非常数类型的指针可以转换为void*,而指向任何类型的指针可以转换为const void*
(强调地雷)Source
这意味着b.m_a可以隐式转换为void*,而b.m_b可以隐式转换为const void*,而不是void*
因此,要解决您的问题,您应该向p2添加一个低级常量,如下所示:

  1. vvvvv-------------------->low level const added
  2. const void *p2 = b.m_b; // works now

Demo

相关问题