strcpy的签名是否有原因:
char *strcpy(char *dest, const char *src);
而不是这个?
char *strcpy(char *const dest, const char *src);
据我所知,该函数永远不会改变指针。
我是否误解了应该使用的const指针?在我看来,当我写的函数接受一个不会被改变的指针(通过realloc等)时,我将它标记为一个const指针,这样可以确保调用者不会在它们上移动它们的指针。 (如果它们有其他结构/等等,引用那个过时的指针位置)
这是一种不错的做法,还是会产生意想不到的后果?
答案 0 :(得分:11)
strcpy
的源代码非常粗略:
char *strcpy(char *dest, const char *src)
{
while (*dest++ = *src++);
}
这里我们实际上修改了dest
但这对调用者没有任何影响,因为在strcpy
函数内,dest
是一个局部变量。
但是下面的代码将无法编译,因为dest
是const:
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
变量。
答案 1 :(得分:3)
声明(原型)中函数参数的限定符完全忽略。这是C语言所要求的,这是有道理的,因为这种限定可能对函数的调用者没有任何可能的意义。
在const char *src
的情况下,参数src
不符合条件;它指向的类型是合格的。在dest
的假设声明中,限定符适用于dest
,因此毫无意义。
答案 2 :(得分:2)
{
"myObject ":{
"myChildObject":"FooBar"
}
}
表示指针char *foo(char *const dest, const char *src) { ... }
在函数体中不会改变。
这并不意味着dest
指向的数据会发生变化,也不会发生变化。
dest
确保const char *src
指向的数据的调用代码不会更改。
在调用src
或strcpy(d,s)
之类的函数时,调用代码并不关心函数是否更改其指针的副本。所有调用代码都关心的是foo(d,s)
或s
指向的数据是否已更改,并且是由d
左侧的const
控制的
*
答案 3 :(得分:1)
按照你的建议将它标记为const是没有意义的。在C中,函数参数作为副本传递。这意味着dest
内的变量strcpy()
实际上是一个新变量(在堆栈上推送),它保存相同的内容(这里是地址)。
看看这个函数原型:
void foo(int const a);
这没有语义价值,因为我们知道传递给foo()
的原始变量a不能更改,因为它是副本。只有副本可能会更改。当foo返回时,我们保证原始变量a
不变。
在函数参数中,如果函数实际上可以持久地更改变量的状态,则只想使用关键字const。例如:
size_t strlen(const char *s);
这将变量s
的内容(即,存储在地址s
处的值)标记为const。因此,当strlen返回时,保证您的字符串不会改变。
答案 4 :(得分:-1)
据我所知,该函数永远不会改变指针。
是的,但你可以。您可以自由更改指针。无需使用dest
指针const
。
例如:
int main(void)
{
char *s = "Hello";
char *d = malloc(6);
strcpy(d, s);
puts(d);
strcpy(d, "World");
puts(d);
}