有没有办法可以将const
关键字添加到作为参数传递的数组中来运行:
void foo(char arr_arg[])
如果我在const
(char
)之前或void foo(const char arr_arg[])
之后char
放置void foo(char const arr_arg[])
,那就意味着char
是常数,而不是arr_arg
。
我刚才read在幕后,作为参数发送的数组被表示为指针,因此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
与数组表示法[]
保持一致的语法。
答案 0 :(得分:18)
在C语言中,您必须将const
放在<{em> []
之间,无论多么奇怪,都可能看起来毫无准备的人
void foo(char arr_arg[const]);
这是“新”C99-specific syntax。在C89 / 90或C ++中,没有办法使用“数组”语法,所以你必须切换到等效的“指针”语法,如David的回答所示。
答案 1 :(得分:8)
首先,在你的特定签名中,参数被编译器转换为指针,所以你拥有的是:
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-ed类型进行推理更简单(通过在表达式中执行直接替换)。鉴于typedef char* char_p;
,const char_p
和char_p const
都等同于char * const
且与const char *
不同。通过在右侧持续使用const
,您可以盲目地替换typedef并阅读类型而无需推理。
答案 2 :(得分:2)
是的,在C中这是可能的,因为C99:
void foo(char ptr_arg[const]);
是有效的语法,等同于
void foo(char *const ptr_arg);
更一般地,[]
可以包含任何类型限定符static
和整数表达式。但是
可选类型限定符和关键字
static
仅出现 在一个带有数组类型的函数参数的声明中,然后 仅在最外层的数组类型派生中。
对于与指针声明等效的维度。
答案 3 :(得分: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]) {}
答案 4 :(得分:0)
对于C ++,Mooing Duck使用模板的答案是最直接的。
如果您的C代码调用C ++实现的C接口,那么您很难将参数转换为指针参数,并使const
如果您使用Boost's array而不是直接使用C数组,那么您可以制作const
,尽管它也是模板函数:
template <unsigned N>
void foo (Boost::array<char, N> const & arg) {}
Boost::array
的优点在于它使您能够从堆栈中轻量分配数组,但能够完全使用依赖于容器中特征的STL算法。