下面的代码不能用gcc 10.2.1编译:
struct Bar {
unsigned char *m_a;
unsigned char m_b[1];
};
int main()
{
Bar bar;
const Bar &b = bar;
void *p1 = b.m_a; // Ok
void *p2 = b.m_b; // Error
return 0;
}
编译器错误为:
错误:从'const void*'到'void*'的转换无效[-fpermissive]
我可以通过使用void *p2 = (void *)b.m_b;
或void *p2 = const_cast<unsigned char *>(b.m_b);
来修复这个问题,但是,编译器似乎没有对成员的常量进行相同的处理。
我猜有一个“额外的检查”的数组,而不是与指针,但为什么呢?
- 谢谢-谢谢
3条答案
按热度按时间oiopk7p51#
拥有
const
结构会将const
加入所有成员。将
const
加到unsigned char *
得到unsigned char * const
(也就是说,指针不能改变为指向其他任何东西,但可以改变所指向的值)。这可以被强制转换为void *
,因为它也是指向非const
的指针。将
const
与unsigned char[1]
相加得到const unsigned char[1]
(T
的const
数组实际上是const T
的数组)。这可以衰减为const unsigned char *
指针,该指针可以强制转换为const void *
,而不是void *
,因为数组的元素不能被修改,这与指向的对象的第一个成员不同。nwlqm0z12#
这是一个
unsigned char *
。它很高兴被转换为void *
。这是一个
const unsigned char *
,这就是数组在C和C++中的工作方式:数组的名字会变成一个指针指向数组中的第一个值。这个数组是const
,所以它变成了const unsigned char *
,你不能把它转换成void *
。请注意,如果您尝试将
&b.m_a
转换为void *
,也会得到相同的错误。b.m_a
本身是const
,但它并不指向const
对象。这是两件非常不同的事情:const
指针和指向const
的指针。tcomlyy63#
表达式
b
的类型为const Bar
,这意味着数据成员m_a
为unsigned char *const
,m_b
为const unsigned char [1]
。现在,需要注意的重要事项是that:
指向任何非常数类型的指针可以转换为
void*
,而指向任何类型的指针可以转换为const void*
(强调地雷)Source
这意味着
b.m_a
可以隐式转换为void*
,而b.m_b
可以隐式转换为const void*
,而不是void*
。因此,要解决您的问题,您应该向
p2
添加一个低级常量,如下所示:Demo