所以,我知道char const *,char * const和char const * const之间的区别。那些是:
char * the_string:我可以更改the_string指向的char, 我可以修改它指向的字符。
const char * the_string:我可以更改the_string的char 点,但我不能修改它指向的字符。
char * const the_string:我无法更改the_string所在的char 点,但我可以修改它指向的字符。
const char * const the_string:我无法将char更改为哪个 the_string指向,也不能修改它指向的char。
(来自const char * const versus 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 *
,因为你可以修改内容,你可能需要分配更多的内存,所以你可能需要修改指针)
我希望有人能够清楚地告诉我这件事。感谢。
答案 0 :(得分:6)
在这种情况下,指针本身是否为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允许函数直接使用堆栈中的值,而无需先复制/转换它们。
答案 1 :(得分:5)
const char *
代表合同。这是一个承诺,该函数不会使用该指针来修改用户传递的内容。指针本身是否恒定不太有价值。
因此,对于调用者来说,指针本身是否为const
没有任何区别。
在许多实现中,“string”函数定期修改传递的指针而不修改内容。如果规范(C标准)要求指针本身保持不变,对于所有实现来说都是一个限制因素,而不会给调用者带来任何好处。
作为旁注,我认为你不应该做所有事情const
然后按照自己的方式行事。如果感觉,只需制作内容const
,该功能就没有理由改变它。简而言之,不要疯狂,它不是灵丹妙药而可以成为挫折的食谱。
答案 2 :(得分:3)
非定义声明:
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)
的标头,反之亦然,请查看标头并搜索来源。他们需要一个更聪明的搜索词。
答案 3 :(得分:3)
当你将一个函数参数声明为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;
}
答案 4 :(得分:2)
char const *s
:s
是指向const char
。char *const s
:s
是指向char
的常量指针。当s
是函数参数时,第一种表示法比第二种表示法更有用。
char const *
,您无法修改指向的值。char *const
,您无法修改指针的值。它与函数参数中的int const
类似:您无法直接对参数执行操作。它不会改变调用函数的任何内容。 (现在,它对编译器几乎没用,但对程序员来说很有意义)