Const与数组到指针的转换

时间:2015-05-20 14:15:26

标签: c++ arrays type-conversion const language-lawyer

import lotus.domino.*; public class ExampleAgent1 extends AgentBase { public void NotesMain(){ try{ Session session = getSession(); AgentContext context = session.getAgentContext(); /* insert logic here (obviously the statement to retrieve POST-data) */ } catch(Exception exc){ System.out.println("Unknown error occured"); } } } 中的constness处理是否是故意的,或者看起来像是一个bug(编译器还是标准)?我可以看到这是怎么发生的,但它仍然感觉很奇怪(至少我希望fa也被视为一个错误 - 就像在a = "qwe"中一样。)

fs

[MinGW 4.9.1]

澄清:我理解这种转换的一般方式,因此"我可以看到这种情况如何发生"部分。这个问题的关键是:(a)std引用(感谢那些提供它们的人),以及(b)是否存在这种怪癖的实际理由(这非常违反直觉)。

4 个答案:

答案 0 :(得分:3)

A的类型为char[8]const Aconst char[8]。因此,fa的参数是const char[8],它衰减到指针const char*,所以fa中的所有内容都很好,因为您正在分配字符串文字(类型为{{ 1}})指针const char[SIZE])。

a的类型为Pchar*具有类型const P(不是char* const),因为const应用于指针。因此,您无法将const char*分配给其他指针。 p是正常的,因为您正在指定指针指向的位置。因此,第二个函数*p = 'Q'也可以按预期运行。

答案 1 :(得分:2)

这是正确的:fa的参数类型是const char *,而不是char * const。这是数组声明含义的微妙之处,以及将数组类型调整为指针类型作为函数参数。

首先调整数组类型本身:

  

C ++ 11 8.3.4 / 1:任何类型的形式“N T的cv-qualifier-seq数组”都被调整为“n cv-qualifier-seq T的数组”

所以最初,类型变为const char"的数组。然后,因为它是一个函数参数,所以进一步调整类型:

  

C ++ 11 8.3.5 / 5:任何类型为“T of array”的参数[...]   调整为“指向T的指针”

所以最终的类型是"指向const char"或const char *的指针。因此,如您的示例所示,您可以修改指针,但不能修改它指向的数据。

对于其他示例,参数类型本身是const:对于fp它的char * const,允许修改数据而不是指针;对于fp它的const string,根本不允许修改。

答案 2 :(得分:1)

此功能声明

void fa( const A a );

相当于

void fa( const char a[8] );

反过来相当于

void fa( const char *a );

并且所有这些函数在函数中声明了相同的一个函数,参数的类型为const char *,就像在上一个函数声明中一样。

另一方面,字符串文字具有常量字符数组的类型,表达式中也会隐式转换为指向其第一个元素的指针。

因此在这个任务中

a = "qwe"; // ok

类型为const char[4]的字符串文字“qwe”被隐式转换为const char *类型。

因此,作业的左侧具有类型const char *,而作业的右侧具有相同的类型const char *

所以没有问题。

在本声明中考虑到

const A a

typedef name替换原始类型,你得到

const char[8]

考虑到根据C ++标准(3.9.3 CV限定符)

  

2 ...应用于数组类型的任何cv限定符都会影响数组   元素类型,而不是数组类型(8.3.4)。

另一方面,在本声明中

const P p

P被替换为char *,你得到char * const,你得到的常量指针可能不会改变它的值。

答案 3 :(得分:0)

参数列表中的数组很奇怪。

in

正如您所料,void foo(char a[10], char b) { char c[10]; char d; } sizeof(d)都是sizeof(b)。和1一样,正如所料。

但是sizeof(c)==10将是4或8,具体取决于您平台的位数。它将是指针的大小。

基本上,参数列表中的数组与其他地方的数组不同。

所以sizeof(a)确实是一个数组,你无法做c

但编译器将使用指针静默替换参数中的数组。因此,c = "hi";会被重写为void foo(char a[10], char b)

void foo(char *a, char b)在被重写为指针之前应用于数组 - 因此你得到一个指向const字符的非const指针。

这里的教训是参数中的数组基本上没用。所有尺寸信息都丢失了。编译器不会停止将大型数组传递给较小的数组参数。

在参数列表中使用数组的唯一有用方法是作为参考。

const

在这种情况下,如果传递的数组不包含10个元素,则会收到错误消息。如果您分配给数组或数组元素,您将获得所期望的行为。

您可以使用模板来记住'如果你需要知道数组的大小。

void foo(char (&a)[10], b) {
}