为什么 strcpy 不为 dest 使用 const 指针?

Why doesn't strcpy use a const pointer for dest?

为什么strcpy的签名是这样的:

char *strcpy(char *dest, const char *src);

而不是这个?

char *strcpy(char *const dest, const char *src);

据我所知,函数永远不会改变指针。

我是不是误解了 const 指针的用途?在我看来,当我编写的函数接受一个不会更改的指针(通过 realloc 等)时,我将其标记为 const 指针,这样调用者就可以确信他们的指针不会在它们上面移动。 (以防他们有其他 structs/etc。引用该指针位置会变得过时)

这是一个好的做法,还是会产生意想不到的后果?

strcpy 的源代码大致是这样的:

char *strcpy(char *dest, const char *src)
{
  while (*dest++ = *src++);
}

这里我们实际上修改了 dest 但这对调用者没有影响,因为在 strcpy 函数内部, dest 是一个局部变量。

但以下代码无法编译,因为 dest 是常量:

char *strcpy(char * const dest, const char *src)
{
  while (*dest++ = *src++);
}

我们需要这样写:

char *strcpy(char * const dest, const char *src)
{
  char *temp = dest;
  while (*temp++ = *src++);
}

引入了一个不必要的 temp 变量。

函数参数上的限定符在声明(原型)中完全被忽略。这是 C 语言所要求的,而且它是有道理的,因为这种限定可能对函数的调用者没有任何意义。

const char *src的情况下,参数src不是合格的;它指向的类型是合格的。在您对 dest 的假设声明中,限定符适用于 dest,因此没有意义。

As far as I know, the function will never change the pointer.

是的,但你可以。您可以自由更改指针。无需制作 dest 指针 const

例如:

int main(void)
{
    char *s = "Hello";
    char *d = malloc(6);

    strcpy(d, s);
    puts(d);
    strcpy(d, "World");
    puts(d);
}

按你说的标记为const是没有意义的。在 C 中,函数参数作为副本传递。意思是strcpy()里面的变量dest其实是一个新变量(压栈),里面的内容(这里是地址)是一样的

看这个函数原型:

void foo(int const a);

这没有语义值,因为我们知道我们传递给 foo() 的原始变量 a 不能更改,因为它是一个副本。只有副本可能会发生变化。当fooreturn时,我们保证原变量a不变

在函数参数中,只有当函数实际上可以持续改变变量的状态时,您才希望使用关键字 const。例如:

size_t strlen(const char *s);

这将变量s的内容(即存储在地址s指向的值)标记为const。因此,你保证你的字符串在 strlen returns.

时不会改变。

char *foo(char *const dest, const char *src) { ... }表示指针dest在函数体中不会改变。

不代表dest指向的数据会变或不会变

const char *src 确保调用代码 src 指向的数据不会改变。

在调用像 strcpy(d,s)foo(d,s) 这样的函数时,调用代码不关心函数是否更改 它的 指针副本。所有调用代码关心的是 sd 指向的数据是否被更改,这是由 *[=22] 左侧的 const 控制的=]

char *dest,     // data pointed by `dest` may or may not change.
const char *src // data pointed by `src` will not change change because of `src`.