Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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++_C_Arrays_Pointers_Constants - Fatal编程技术网

C++ 我可以传递伪装成数组的常量指针吗?

C++ 我可以传递伪装成数组的常量指针吗?,c++,c,arrays,pointers,constants,C++,C,Arrays,Pointers,Constants,相当于: void foo(const char *s); 是否有与以下两种类似的等价物 void foo(const char s[]); 这在某些情况下很有用: void foo(char * const s); void foo(const char * const s); 在C中: class AA { void foo(char a[]); void foo(const char a[]); }; void AA::foo(char* const a) { … } vo

相当于:

void foo(const char *s);
是否有与以下两种类似的等价物

void foo(const char s[]);

这在某些情况下很有用:

void foo(char * const s);
void foo(const char * const s);
在C中:

class AA {
  void foo(char a[]);
  void foo(const char a[]);
};

void AA::foo(char* const a) { … }
void AA::foo(const char* const a) { … }

不能在C89中使用,但在C99中可以将等价物声明为:

extern void foo(char a[]);
extern void fooc(const char a[]);


void foo(char* const a) { … }
void fooc(const char* const a) { … }

<>在C++中,编译器自动将类型T的n个元素数组的函数参数(其中代码< >n>代码>未知)转换成指向t的指针。在同一变换顶层<代码> const 中,参数的限定符被删除:

void foo(char s[const]);
void foo(const char s[const]);
这意味着在指针的情况下,顶级常量限定符被删除,而在数组的情况下,它被转换为指向的指针。另一方面,你不能将两者混合,因为你不能声明一个由N个T类型元素组成的常量数组,因为数组总是常量。这意味着你不能写:

void f( const int x ); // => declares: void f( int )
void f( int * const ); // => declares: void f( int* )
因为参数的类型无效。如果它是有效类型,则转换将应用,但因为它不是有效类型,编译器将在尝试执行转换之前拒绝代码

这在C++03标准的§8.3.5/3中进行了处理(可能在C++11中接近)

单个名称可用于单个范围内的多个不同功能;这是函数重载(第13条)。具有给定参数列表的函数的所有声明应在返回值的类型以及参数的数量和类型上完全一致;省略号的存在或不存在被视为函数类型的一部分。函数的类型使用以下规则确定。每个参数的类型由其自己的decl说明符seq和声明符确定。在确定每个参数的类型后,“T数组”或“函数返回T”类型的任何参数都将分别调整为“指向T的指针”或“指向函数返回T的指针”。生成参数类型列表后,对这些类型进行若干转换以确定函数类型删除修改参数类型的任何cv限定符。[示例:类型
void(*)(const int)
变为
void(*)(int)
-结束示例]此类cv限定符仅影响函数体中参数的定义;它们不会影响函数类型。
如果存储类说明符修改参数类型,则会删除说明符。[示例:register char*变为char*-end Example]此类存储类说明符仅影响函数体中参数的定义;它们不影响函数类型。转换后的参数类型列表是函数的参数类型列表

请注意,由于编译器将执行该转换,因此最好按照最少意外的原则编写编译器将要使用的实际类型:

void f( const int a[] const );  // Invalid type definition
编译器不会检查传递的数组是否有10个元素,它会将声明读取为
void f(int*)
,并乐意接受包含较少元素的数组或甚至没有数组的调用(指向单个int的指针)。在实际代码中使用指针:

void f( int a[10] ) { a[5] = 7; }

可能会在代码复查中触发一些警报:我们是否保证在对
f
的所有调用中,参数至少有6个元素大?我们是否也应该传递大小以防万一?

我认为指针可以为null,而数组参数不能为null(并且编译器可以在知道这一点的情况下进行优化;但是在一个简单的示例gcc-4.6中,即使使用-O3,也不要进行这样的优化)

我希望编译器会以不同的方式优化下面的两个函数。事实并非如此。我手头没有我的C标准来检查它是否可以删除下面ss中的测试

void f( int *a ) { a[5] = 7; }

调用方不在乎您是否承诺不更改(you=
foo
)局部变量(
s
),因此我看不到本例中
const char*
const char*const
的区别。您可能会发现这很有用:
void foo(char*const s)只是一个声明。
void foo(char*const s)没有差异
无效foo(char*s)代码> const <代码>对于函数定义非常重要:<代码>无效FO(char * const s){…} /Cord>您是否询问C、C++或两者?它们是非常不同的语言。@AlexeyMalistov:我实际上是在询问定义,但为了保持示例代码简短,我只发布了声明。愚蠢的我…@Chris Lutz这不符合“传递伪装成数组的常量指针”的条件吗?@Justin:问题不仅仅是标题。你的回答与问题的主体无关。@Gorpik我认为它也与主体有关。我还注意到,它在某些情况下会很有用。此表单当然有有效的用途,在这些情况下它满足了问题和正文。正文询问如何将声明从获取
char*const a
更改为使用
[]
而不是
*
的声明。上面的第一个答案说你应该像回答问题的
chara[const]
一样传递它。在您的回答中,我没有看到任何
[]
s@Shahbaz我回答中的每个声明都使用
[]
。问题是标记C和C++——GCC和CLAN(我测试的唯一编译器)都被拒绝为<代码> char A[const ] < /C> >编译为C++。我的回答是一个既满足C又满足C++的实用解决方案。有些人确实使用这种形式。+1因为编译器将执行这种转换,所以最好按照最少意外的原则编写编译器将要使用的实际类型。很好。后面的文本也很好。不,在
ss
函数中,
t
不是数组;它的实际类型是
int*
。不管代码实际上说了什么,编译器都会转换所有数组类型参数(
T)
int s (int *t)
{
  if (!t)
    return 0;
  return t[0] + t[1];
}


int ss (int t[])
{
  if (!t) // never false, since t is an array!!
    return 0;
  return t[0] + t[1];
}