为什么strcpy不使用dest指针的const指针?
是否有一个原因的strcpy的签名是这样的:为什么strcpy不使用dest指针的const指针?
char *strcpy(char *dest, const char *src);
,而不是这个?
char *strcpy(char *const dest, const char *src);
据我所知,函数永远不会改变指针。
我误解了什么const指针应该用于?在我看来,当我写一个函数接受一个不会被改变的指针(通过realloc等),然后我把它标记为一个const指针,这样调用者可以确定它们的指针不会被移动。 (如果他们有其他结构/等参考指针位置将变得过时)
这是一种好的做法,或者它会产生意想不到的后果吗?
为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
变量。
注意:3个例子不会返回值为'char * strcpy()'函数渲染它们UB - 当然它们是_rough_。看到没有“非必要的临时变量”的代码会很有趣,它会返回C库中指定的原始“dest”。 – chux
@chux你完全正确,但它仅用于演示目的。 –
函数自变量的限定符在声明(原型)中完全被忽略。这是C语言所要求的,它是有道理的,因为这样的限定没有可能对函数的调用者有意义。
在const char *src
的情况下,参数src
不是合格的;它指向的类型是合格的。在dest
的假设声明中,限定符适用于dest
,因此无意义。
据我所知,函数永远不会改变指针。
是的,但你可以。你可以自由改变指针。无需制作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()
,因为它是一个副本。只有副本可能会改变。当foo返回时,我们保证原始变量a
不变。
在函数参数中,只有当函数实际上可以持久地改变变量的状态时,才想使用关键字const。例如:
size_t strlen(const char *s);
这标志着可变s
为const(即,存储在该地址s
点值)的含量。因此,你保证你的字符串在strlen返回时不会改变。
char *foo(char *const dest, const char *src) { ... }
表示指针dest
在函数体内不会改变。
这并不意味着dest
指向的数据将会或不会改变。
const char *src
确保调用代码src
指向的数据不会改变。
在调用像strcpy(d,s)
或foo(d,s)
这样的函数时,调用代码并不关心函数是否更改指针的的副本。所有调用代码关心的是如果数据指向s
或d
改变,这是由*
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`.
左侧的
const
我觉得一个常数,只能被初始化/ assighned /定义一次控制或在声明时定义。 –不仅_函数不会改变pointer._,但是即使没有const,strcpy也无法改变dest。 –