[英]const char * VS char const * const (Not about what is const)
所以,我知道char const *,char * const和char const * const之间的区别。 那些是:
char * the_string:我可以更改the_string指向的char,我可以修改它指向的char。
const char * the_string:我可以更改the_string指向的char,但是我无法修改它指向的char。
char * const the_string:我无法更改the_string指向的char,但我可以修改它指向的char。
const char * const the_string:我不能更改the_string指向的char,也不能修改它指向的char。
(来自const char * const与const char *? )
现在,我的问题是:假设我正在编写一个不会修改传递给它的C字符串的函数,例如:
int countA(??? string) {
int count = 0;
int i;
for (i=0; i<strlen(string); i++) {
if (string[i] == 'A') count++;
}
return count;
}
现在,标题应该是什么?
int countA(char const * string);
int countA(char const * const string);
我的感觉是我应该使用第二个,因为我不会修改指针本身,也不会修改数组的内容。 但是,当我查看标准函数的标题时,他们使用第一个。 例
char * strcpy ( char * destination, const char * source );
为什么?
(实际上char const *
对我来说真的没有意义,因为如果你正在考虑抽象字符串,要么你没有修改字符串(所以, char const * const
因为你没有修改指针,所以内容)或你将修改字符串(所以只是char *
因为,你可能会修改内容,你可能需要分配更多的内存,所以你可能需要修改指针)
我希望有人能够清楚地告诉我这件事。 谢谢。
在这种情况下,指针本身是否为const并不重要,因为它无论如何都是按值传递的:无论strcpy
对source
什么都不会影响调用者的变量,因为strcpy
将在调用者的source
副本上运行堆栈,而不是原始。 请注意我说的是指针值 ,不是什么指针指向 ,这显然应该不会改变,因为它是源参数。
char dest[10];
char const * source = "Hello";
strcpy( dest, source );
// no matter what strcpy does, the value of source will be unchanged
在strcpy
,您需要迭代destination
和source
指向的数组上的指针。 不将参数声明为const允许函数直接使用堆栈中的值,而无需先复制/转换它们。
拥有const char *
代表合同 。 这是一个承诺,该函数不会使用该指针来修改用户传递的内容。 指针本身是否恒定不太有价值。
因此,对于调用者来说,指针本身是否为const
都没有任何区别。
在许多实现中,“字符串”函数定期修改传递的指针而不修改内容。 如果规范(C标准)要求指针本身保持不变, 那么它将成为所有实现的限制因素 ,而不会给调用者带来任何好处。
作为旁注,我认为你不应该把所有东西都做成const
然后再绕过它。 如果觉得函数没有理由改变它,只需要制作const
。 简而言之,不要疯狂, 它不是一颗银弹 , 可以成为挫折的秘诀。
非定义声明:
int countA(char const * string);
int countA(char const * const string);
int countA(char const * foobar);
int countA(char const *);
都是等价的。 string
参数名称(实际上)是countA
实现中的局部变量。 无论调用者是否修改了该变量,调用者的业务都不是,并且它不会影响函数的签名。
调用者的业务是否函数修改string
的referand ,因此第一个const很重要。 调用变量的名称略微是调用者的业务,但仅仅因为约定是将声明中的参数命名为提示它们用于什么。 文档是完全传达每个参数含义的方式,而不是它的名称。
如果你想要一个规则:省略第二个const
,因为它在告诉调用者没有任何用处的同时使声明混乱。
您可以将它包含在函数定义中 ,但这样做有一些问题。 您需要使标题与定义保持同步(在这种情况下,由于实施细节的更改不会影响调用者,您有时会发现自己更改标题)。 或者你必须接受标题与定义不匹配,这有时会让看不见的人感到不安:
int countA(char const * const string) {
return 0;
}
并在头部搜索int countA(char const * const string)
,反之亦然,请查看标题并搜索源代码。 他们需要更智能的搜索词。
当你将一个函数参数声明为const char * const
,它与来自const char *
调用者没有什么不同:他们不关心你对该指针做什么,因为对它们而言,无论如何它都是“按值传递”。
第二个const
适用于您,而不适合您的用户。 如果你知道你不打算修改那个指针,那么无论如何都要声明它为const char * const
:它将帮助你和维护代码的其他人以后捕获错误。
至于标准库,我的猜测是他们不想让它成为const char * const
因为他们想要修改poitners的能力:
char * strcpy ( char * destination, const char * source ) {
char *res = destination;
while (*destination++ = *source++)
;
return res;
}
char const *s
: s
是指向const char
的指针。 char *const s
: s
是一个指向char
的常量指针。 当s
是函数参数时,第一种表示法比第二种表示法更有用。
char const *
,您无法修改指向的值。 char *const
,您无法修改指针的值。 它就像函数参数中的int const
:你不能直接对你的参数进行操作。 它不会改变调用函数的任何内容。 (现在,它对于编译器来说几乎没用,但它对程序员来说很有意义)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.