赋值 = :不兼容的指针
当我编译这样的东西
double da[ 3 ] = { 2., 3., 4. }; double (* pda)[ 3 ] = &da; double const (* cpda)[ 3 ] = pda; // gcc: warning; MSVC: ok
gcc警告我
warning: initialization from incompatible pointer type [enabled by default]
问题:这项任务有什么问题? 是的,从技术上讲,这些是不同的类型,但我没有看到任何危险, double const (*)[ 3 ]
看起来比double (*)[ 3 ]
更安全。
我做了一些测试,结果让我更加困惑:
1)MSVC非常满意double const (* cpda)[ 3 ] = pda;
分配,没有错误,没有警告。
2)gcc和MSVC都很满意
double d = 1.; double * pd = &d; double const * cpd = pd; // gcc: ok; MSVC: ok
虽然这些也是不同的类型。
3)在这个例子中
double d = 1.; double * pd = &d; double * * ppd = &pd; double const * * cppd = ppd; // gcc: warning; MSVC: error
gcc给出相同的警告,但MSVC给出错误(!)。
谁在这? gcc还是MSVC?
检测结果。
编译:
1)gcc版本4.7.2: http : //www.compileonline.com/compile_c_online.php
2)用于x86的MSVC(作为C ++代码)版本’VS2012CTP’17.00.51025: http ://rise4fun.com/vcpp
3)MSVC(作为C代码)VS2010:离线测试
int main() { double d = 1.; double * pd = &d; double const * cpd = pd; // gcc: ok // MSVC C++: ok // MSVC C: ok double * * ppd = &pd; double const * * cppd = ppd; // gcc: warning: initialization from incompatible pointer type [enabled by default] // MSVC C++: error C2440: 'initializing' : cannot convert from 'double **' to 'const double **' // MSVC C: ok double da[ 3 ] = { 2., 3., 4. }; double (* pda)[ 3 ] = &da; double const (* cpda)[ 3 ] = pda; // gcc: warning: initialization from incompatible pointer type [enabled by default] // MSVC C++: ok // MSVC C: ok cpd, cpda; return 0; }
编辑:
我刚刚在我的Visual Studio上将其编译为C代码(而不是C ++)并且它没有提供任何错误,也没有任何警告。 我编辑了以上代码的评论
gcc
就在这里,C中需要诊断。
double da[ 3 ] = { 2., 3., 4. }; double (* pda)[ 3 ] = &da; double const (* cpda)[ 3 ] = pda; // diagnostic here
基本上,您正在尝试将类型为T1
的对象分配给类型为T2
的对象(简单赋值的约束适用于初始化)。
其中T1
是指向T
的数组N
的指针。
T2
是指向const T
的数组N
的指针。
在简单赋值的约束中,C表示对于指针,以下内容应该成立(在C99中,6.5.16.1p1):
两个操作数都是指向兼容类型的限定或非限定版本的指针,左边指向的类型具有右边指向的所有类型的限定符。
这将允许例如:
int a = 0; const int *p = &a; // p type is a qualified version of &a type
但在您的示例中,指向const T
的数组N
的指针不是指向T
的数组N
的指针的限定版本。 在C中,数组不能是常量:没有const
数组,只有const
数组的数组。
这是对标准解释的不同,gcc认为类型不兼容,而MSVC和clang则不同。
6.7.6.1(2):
要使两个指针类型兼容,两者都应具有相同的限定条件,并且两者都应是兼容类型的指针。
pda
和cpda
的类型是相同的[完全不合格],所以问题是它们是否指向兼容类型,即double[3]
和const double[3]
兼容类型?
6.7.6.2(6):
要使两个数组类型兼容,两者都应具有兼容的元素类型,如果两个大小说明符都存在,并且是整数常量表达式,则两个大小说明符应具有相同的常量值。 如果在要求它们兼容的上下文中使用这两种数组类型,则如果两个大小说明符计算为不相等的值,则它是未定义的行为。
所以问题是double
和const double
是否是兼容类型。
6.7.3(10):
要使两种合格类型兼容,两者都应具有相同类型的兼容类型; 说明符或限定符列表中类型限定符的顺序不会影响指定的类型。
我会说使double
和const double
不兼容,所以gcc是对的。
初始化
double const * cpd = pd;
没关系,因为6.5.16.1列表中的赋值约束(与初始化相关)
左操作数具有primefaces,限定或非限定指针类型,并且(考虑左值操作数在左值转换后将具有的类型)两个操作数都是指向兼容类型的限定或非限定版本的指针,左侧指向的类型具有全部右边指出的类型的限定词;
作为可接受的情况之一。 cpd
和pd
都指向double
限定版本,左操作数的目标具有右边的所有限定符(以及另一个const
)。
但是, double*
和const double*
类型不兼容
double const * * cppd = ppd;
再次无效,需要诊断消息。
这是C和C ++之间的区别。 在C ++中进行这种类型的const转换是完全正常的,但在C语言中则不行。