- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
当我编译这样的东西时
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 认为类型不兼容,而 MSVC 和 clang 认为。
6.7.6.1 (2):
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
pda
和 cpda
的类型是相同限定的[完全没有限定],所以问题是它们是否指向兼容的类型,即 double [3]
和 const double[3]
兼容类型?
6.7.6.2 (6):
For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.
所以问题是 double
和 const double
是否兼容类型。
6.7.3 (10):
For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.
我会说这使得 double
和 const double
不兼容,所以 gcc 是正确的。
初始化
double const * cpd = pd;
没问题,因为 6.5.16.1 列表中的赋值约束(与初始化相关)
the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;
作为可接受的情况之一。 cpd
和 pd
都指向 double
的限定版本,左操作数的目标具有右操作数的所有限定符(还有一个,const
).
但是,类型double*
和const double*
不兼容,因此
double const * * cppd = ppd;
再次无效,需要诊断消息。
关于c - 赋值 <指向常量数组的指针> = <指向数组的指针> : incompatible pointers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17122727/
在指向指针的指针上使用指针算术是否定义明确? 例如 int a=some_value; int* p=&a; int**p2=&p; 现在对 p2 执行算术是否是定义明确的行为?(例如 p2+1、p2
我正在尝试使用一个函数来替代 C 中的 scanf()。该函数是由第三方编写的,并进行了相应的定义: ScanDecimal16uNumber - Scans a decimal 16bit unsi
我正在尝试为 Sundials CVODE 编写 CFFI 包装器图书馆。 SWIG 被 Sundial header 阻塞,因为它们相互关联,并且 SWIG 找不到合适的 header ,所以我手工
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: pass by reference not working 我正在阅读一些教程 linklistproblem在互联
我有一个代码片段很难理解。 char *c; // c is uni dimensional table ( single row ) char **p ; // p is a two dimen
我正在将一些代码移植到 Windows 并且被难住了。有一些代码在启动时自动运行以将指针复制到指针,并在退出时再次运行以删除指向指针的指针(如果它不为空)。 我已经创建了一个示例程序来重现该行为 in
将非 const 指针转换为 const 指针是合法的。 那为什么将指向非const的指针转换为指向const的指针是不合法的呢? 例如,为什么下面的代码是非法的: char *s1 = 0; con
将非 const 指针转换为 const 指针是合法的。 那为什么将指向非const的指针转换为指向const的指针是不合法的呢? 例如,为什么下面的代码是非法的: char *s1 = 0; con
将指向非常量的指针转换为指向常数的指针是合法的。 那么为什么将指向非const的指针转换为指向const的指针是不合法的呢? 例如,为什么下面的代码是非法的: char *s1 = 0; const
之间有什么区别 procedure(some_routine), pointer :: ptr ptr => null() 和 procedure(some_routine), pointer ::
只是为了消除一些困惑。我最近遇到了这段代码(使用指针到指针): int encode(unsigned char type, uint64_t input_length, unsigned char*
我已经阅读了我能找到的有关 C/C++ 指针的内容,但其中大部分是介绍性的,虽然它可以帮助您理解它们的使用,但在许多情况下,现有代码会抛出难以破译的示例。 我确实看到了一些例子,他们将一行代码分解成它
我一直在关注的学习数据结构的书使用“单指针”作为函数中的参数,这些函数在链表的不同位置添加新节点,例如在开始,在结束。同样在删除的情况下使用“pointer-to-pointer”。在所有这些情况下,
考虑这段代码: #define MAX 4 ............ ............ int** ptr = (int**)malloc(sizeof(int*)*MAX); *ptr =
如何将指向 void 对象的指针转换为类对象? 最佳答案 使用 static_cast。请注意,只有当指针确实指向指定类型的对象时,您才必须这样做;也就是说,指向 void 的指针的值取自指向此类对象
我假设一种语言的实现允许您将指针视为整数,包括对它们进行标准算术。如果由于硬件限制这是不现实的,请告诉我。如果编程语言通常没有这么强大的指针运算,但是在实践中是可行的,那么我仍然想知道这种实现BigI
我是一名 nodejs 开发人员,我通常为我的应用程序使用一个结构,该结构包含一个配置包/对象,该对象包含对我常用的库和配置选项的引用。通常,此配置对象也包含我的数据库连接,并且可以通过我的应用程序访
我已经在几个上下文中阅读过“胖指针”这个术语,但我不确定它的确切含义以及它何时在 Rust 中使用。指针似乎是普通指针的两倍,但我不明白为什么。它似乎也与特征对象有关。 最佳答案 术语“胖指针”用于指
这是让我困惑的代码。 static char *s[] = {"black", "white", "pink", "violet"}; char **ptr[] = {s+3, s+2, s+1, s
通用指针允许您创建指向指针的指针: void foo(Object **o) {} int main() { Object * o = new Object(); foo(&o); } s
我是一名优秀的程序员,十分优秀!