繁体   English   中英

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

[英]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并不重要,因为它无论如何都是按值传递的:无论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允许函数直接使用堆栈中的值,而无需先复制/转换它们。

拥有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实现中的局部变量。 无论调用者是否修改了该变量,调用者的业务都不是,并且它不会影响函数的签名。

调用者的业务是否函数修改stringreferand ,因此第一个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 *ss是指向const char的指针。
  • char *const ss是一个指向char的常量指针。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM