const char * VS char const * const(不是什么是const)

时间:2012-07-23 11:24:19

标签: c string const

所以,我知道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 *,因为你可以修改内容,你可能需要分配更多的内存,所以你可能需要修改指针)

我希望有人能够清楚地告诉我这件事。感谢。

5 个答案:

答案 0 :(得分:6)

在这种情况下,指针本身是否为const无关紧要,因为无论如何它都按值传递:strcpysource所做的任何事都不会影响调用者的变量,因为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内,无论如何,您需要在destinationsource指向的数组上迭代指针。不将参数声明为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 *ss是指向const char
  • 的指针
  • char *const ss是指向char的常量指针。

s是函数参数时,第一种表示法比第二种表示法更有用。

  • 使用char const *,您无法修改指向的值。
  • 使用char *const,您无法修改指针的值。它与函数参数中的int const类似:您无法直接对参数执行操作。它不会改变调用函数的任何内容。 (现在,它对编译器几乎没用,但对程序员来说很有意义)