17

有什么方法可以将const关键字添加到作为参数传递给函数的数组中:

void foo(char arr_arg[])

如果我放在( )const之前或( ) 之后,那将意味着它是恒定的,而不是.charvoid foo(const char arr_arg[])charvoid foo(char const arr_arg[])chararr_arg

我刚刚读到,在后台,作为参数发送给函数的数组表示为指针,因此void foo(char arr_arg[])void foo(char* ptr_arg). 考虑到这一点,我可能会重写该功能,void foo(char * const ptr_arg)以使其正是我想要实现的。

但我想知道是否有办法const在此声明中添加关键字以void foo(char arr_arg[])使其与void foo(char * const ptr_arg)(而不是 void foo(char const * ptr_arg)void foo(const char * ptr_arg))相同?

我只是想了解是否有一种语法可以使arr_arg数组表示法保持不变[]

4

5 回答 5

20

在 C中,您必须const []

void foo(char arr_arg[const]);

这是“新”的 C99 特定语法。在 C89/90 或 C++ 中,无法使用“数组”语法来做到这一点,因此您必须切换到等效的“指针”语法,正如 David 的回答中所建议的那样。

于 2012-06-06T20:24:30.627 回答
10

第一件事是,在您的特定签名中,编译器将参数转换为指针,因此您拥有的是:

void foo( char * arg );

现在,有两个实体可以在该签名中设为 const:指针和指向的类型。可以通过两种不同但等效的方式将指向的类型设为 const [*]:

void foo( const char * arg );
void foo( char const * arg );

可以使用以下语法将指针设为 const:

void foo( char * const arg );

但请注意,在函数签名中,与char arg[]转换为指针的方式相同char *arg,顶级限定符被丢弃。所以从声明的角度来看,这两者是等价的:

void foo( char * const arg );
void foo( char *       arg );

在定义中,顶级 const 可用于指示编译器不应在函数内更改参数指针(按值),并且它会检测您是否尝试将指针重置到不同的位置。但是,如果只有指针是 const,那么编译器会很乐意让您修改指向的内存。如果您不希望函数更改数组的内容,那么您应该选择前两个签名之一。

[*] 我更喜欢这种char const *格式,因为它提供了一种读取类型的一致方式:从右到左读取:指向 const char 的非 const 指针。此外,推理类型定义的类型更简单(通过在表达式中执行直接替换)。给定typedef char* char_p;,const char_pchar_p const既等价于char * const又不同于const char *。通过始终const在右侧使用,您可以盲目地替换 typedef 并读取类型而无需推理。

于 2012-06-06T20:23:48.807 回答
2

是的,在 C 中,自 C99 以来这是可能的:

void foo(char ptr_arg[const]);

是有效的语法并且等价于

void foo(char *const ptr_arg);

更一般地说,它[]可以包含任何类型限定符static和一个整数表达式。但

可选类型限定符和关键字static应仅出现在具有数组类型的函数参数的声明中,然后仅出现在最外层的数组类型派生中。

那是等效于指针声明的维度。

于 2012-06-06T20:29:11.753 回答
2

C++ 中有多种方法,但没有一种方法完全符合您的预期。

//typedef has a very clear intent
typedef char* array;
void f0(const array a) {}

//switch to pointers to sidestep the problem
void f1(char* const a) {}

//references are inherently const
//can't take pointers, but guarantees the size, sometimes nice
//this version obviously doesn't work in C
template<int n>
void f2(char (&a)[n]) {}

http://ideone.com/4LvYT

于 2012-06-06T20:55:00.190 回答
0

对于 C++,Mooing Duck 使用模板的答案是最直接的。

如果您有调用 C++ 中实现的 C 接口的 C 代码,则您只能将参数转换为指针参数,然后将其const

如果您要使用Boost 的数组而不是直接使用 C 数组,那么您将能够做到这一点const,尽管它也是一个模板函数:

template <unsigned N>
void foo (Boost::array<char, N> const & arg) {}

的优点Boost::array是它使您能够对堆栈中的数组进行轻量级分配,但能够充分使用依赖于容器中特征的 STL 算法。

于 2012-06-06T20:51:37.897 回答