Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 隐式指针到常量的转换_C_Constants_Language Lawyer - Fatal编程技术网

C 隐式指针到常量的转换

C 隐式指针到常量的转换,c,constants,language-lawyer,C,Constants,Language Lawyer,我想知道C11标准中是否定义了指向常量数据类型指针的隐式转换: T x; const T *p = &x; 指向T类型对象的指针隐式转换为指向const T类型对象的指针。C11标准中是否定义了这种隐式转换?(我知道允许这样做是有意义的,它有多有用。我只是想知道标准中对它的定义) 此外,根据C11,是否禁止从类型T**到const T**的隐式转换 T *p; const T **pp = &p; 这是一个众所周知的问题部分,因此GCC和LLVM/clang会发出警告。我仍然

我想知道C11标准中是否定义了指向常量数据类型指针的隐式转换:

T x;
const T *p = &x;
指向
T
类型对象的指针隐式转换为指向
const T
类型对象的指针。C11标准中是否定义了这种隐式转换?(我知道允许这样做是有意义的,它有多有用。我只是想知道标准中对它的定义)

此外,根据C11,是否禁止从类型
T**
const T**
的隐式转换

T *p;
const T **pp = &p;
这是一个众所周知的问题部分,因此GCC和LLVM/clang会发出警告。我仍然想知道,根据C11标准,这是否是允许的。我只在§6.5.16.1P6中发现一条评论,认为这应该是违反约束的行为。但是,我看不出应该违反哪个约束。我再次知道,这应该被禁止,这种隐式转换可能会导致微妙的问题。我只是想知道根据C11,这是否是(未)定义的行为

同样,我的两个问题不是关于这是好是坏(这里回答了多次),而是C11标准如何/在哪里定义这一点


为了完整起见,这里有一个链接,指向第二个示例有问题的原因:

指向T类型对象的指针隐式转换为 指向const-T类型的对象的指针。这是隐式转换吗 C11标准中定义的某个地方

对。此隐式转换由标准强制执行

第二节说

涉及指针的转换,但 6.5.16.1中的约束条件应通过明确的 演员

第3点中引用的6.5.16.1中指出:

左操作数具有原子指针、限定指针或非限定指针类型, and(考虑左值之后的左操作数的类型) 转换)两个操作数都是合格或不合格的指针 兼容类型的版本,左侧指向的类型 右边所指类型的所有限定符

因此,
const T*p=&x保持不变,因为您只是添加限定符,而不是删除它们

const T**pp=&p
不属于此范围,因此需要显式强制转换(C++允许
const t*const*pp=&p;
(需要第二个常量),但C仍然不允许。)

只要对齐匹配(对于指向不同限定类型的指针,它们将匹配),就UB而言,通过显式转换的指针转换不是问题,因为 保证:

指向对象类型的指针可以转换为指向对象类型的指针 不同的对象类型。如果生成的指针不正确 aligned68)对于引用的类型,行为未定义。 否则,当再次转换回时,结果应相等 指向原始指针。当指向对象的指针转换为 指向字符类型的指针,结果指向最低地址 对象的字节。结果的连续增量,直到 对象的大小,生成指向 反对

但您需要注意访问/取消引用,这些访问/取消引用将由以下内容管理:

对象的存储值只能由左值访问 具有以下类型之一的表达式:88)

与对象的有效类型兼容的类型,限定 与对象的有效类型兼容的类型的版本 类型,该类型是与 对象的有效类型,是有符号或无符号的类型 与有效类型的限定版本相对应的类型 对象,一种聚合或联合类型,包括 其成员中的上述类型(递归地包括 子集合或包含的联合的成员)或字符类型


第6.3.2.3节第2段适用于第一种情况。我的第一个想法也是§6.5.16.1第3段应适用(至少适用于第一种情况)。然而,我的头脑被这样的措辞扭曲了:“两个操作数都是指向兼容类型的合格或不合格版本的指针”。这是否意味着
const T
T
是兼容类型?根据我的理解,它们不是,并且§6.7.3第10段说“对于两种合格类型的兼容,两者应具有兼容类型的相同合格版本”。虽然这不太合适,因为不是两种类型都是限定的。很抱歉,第二次答复中,我的字符已用完;)您能否详细说明为什么第二种情况不属于§6.5.16.1的范围?我的意思是,如果
const T
T
是兼容的,那么
const T*
T*
应该是兼容的,因此§6.5.16.1也应该适用于
const T**
T**
。或者我遗漏了什么(不过,我可能应该休息一下,好好睡一觉)。@MaxMaier类型兼容性似乎是一个定义非常复杂的概念,其定义遍及整个标准(请参阅我在上的问题),但本质上(正如我所理解的那样)在类型的上下文中兼容意味着相同且具有相同的限定条件,警告可能存在不完整的片段:
int
int const
不兼容,但是
int[]/*complete*/
int[42]
兼容(当然,这是不可传递的)。嗯,最后一个例子很简洁。谢谢你澄清这一点!