为何K&R示例中函数返回指针的操作是合法的?
解惑K&R中strcpy返回指针的作用域问题
嘿,这个问题问得太到位了——我当初啃K&R的时候也在这个点上卡了好一会儿!先把你提到的§5.6里的strcpy示例代码贴出来,咱们对着说:
char *strcpy(char *s, const char *t) { char *p = s; while ((*s++ = *t++) != '\0') ; return p; }
你困惑的点核心在于:函数返回后,指针p指向的内存为啥还能用? 其实这里有个关键的区分,咱们拆开来理清楚:
- 首先,函数里的
p是个局部指针变量,它确实会在函数执行完毕后被销毁(因为它存在函数的栈帧里,栈帧弹出后这块内存就不属于当前函数了)。但我们返回的不是p本身的内存,而是p里面存储的地址值。 - 这个地址值是什么?是传入函数的
s的起始地址!而s指向的内存,是由调用strcpy的代码分配的——可能是栈上的数组(比如char dest[20]; strcpy(dest, "test");),可能是堆上的内存(char *dest = malloc(20); strcpy(dest, "test");),也可能是全局变量的内存。这些内存的生命周期完全由调用者控制,和strcpy函数的生命周期没有关系。
你之前的认知完全正确:绝对不能返回指向函数内部局部变量的指针——比如如果有人写了这样的strcpy:
// 错误示例!绝对不能这么写 char *bad_strcpy(const char *t) { char p[100]; int i = 0; while ((p[i] = t[i]) != '\0') i++; return p; }
这里返回的p是局部数组的地址,函数结束后数组的内存会被释放,返回的指针就成了野指针,这才是危险的情况。但K&R的实现完全不一样,它返回的是调用者传入的外部内存的地址,所以完全合法且安全。
总结一下:你混淆了「局部指针变量本身」和「指针变量存储的地址指向的内存」——前者会随函数销毁,后者只要是外部分配的,就依然在作用域内。
内容的提问来源于stack exchange,提问作者Igid
相关产品推荐
相关产品推荐

