[英]C - printing a char* through strcpy is acting contradictory?
我在这里的第一篇文章已经使用了多年,但是这个难题实在令人讨厌。 因此,当我使用C编译器通过VS2015 Developer Command提示符运行以下C代码时:
#include <stdio.h>
#include <string.h>
int main(){
char* ptr = NULL;
const char* pt2 = "hello";
strcpy(&ptr, pt2);
printf("%s",&ptr);
return 0;
}
我收到以下警告:
midterm_c.c(35): warning C4047: 'function': 'char *' differs in levels of indirection from 'char **'
midterm_c.c(35): warning C4024: 'strcpy': different types for formal and actual parameter 1
midterm_c.c(36): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'char **'
但是,当我运行它时,它会显示“ hello”,这不应发生,因为在ptr变量上使用引用运算符没有意义。 但是当我在没有它们的情况下运行此代码时:
char* ptr = NULL;
const char* ptr2 = "hello";
strcpy(ptr, ptr2);
printf("%s",ptr);
return 0;
我没有收到任何警告,可以成功编译,但是当我运行它时,程序崩溃了,尽管它应该可以正常工作。 我真的很沮丧,因为这对我来说毫无意义,也是我现在真正讨厌C的原因之一。 如果有人知道这是怎么发生的,我将非常感激。 谢谢。
在您的工作代码中,您基本上只是将堆栈的一部分视为字符串缓冲区。 按照标准,这显然是非法的,但它确实起作用,因为您在踩踏后不会从踩踏的东西中读取任何内容。
您是正确的,将char**
传递给strcpy
是没有意义的,但是最终发生的事情是,它会写入char*
变量本身(如果是32位程序,还会写入一些相邻的内存),并将其视为一个数组char
(毕竟,一个八字节的指针有足够的空间容纳七个字符串和NUL
终止符)。 实际上,您的代码是不正确的代码,仍然会像正确的代码一样工作,因为这是:
char* ptr = NULL;
const char* pt2 = "hello";
strcpy(&ptr, pt2);
printf("%s",&ptr);
编译为行为几乎完全像这样的代码(除了警告):
char ptr[sizeof(char*)]; // Your char* behaves like an array
const char* pt2 = "hello";
strcpy(ptr, pt2);
printf("%s", ptr);
当您不使用ptr
的地址时,会将NULL
指针传递给strcpy
,该指针将立即崩溃(因为您几乎无法在所有系统上写入NULL
指针的目标)。
当然,正确的解决方案是使ptr
指向已分配的内存,可以是全局,自动或动态分配的内存。 例如,使用堆栈缓冲区,这将是合法的:
char buf[8];
char *ptr = buf; // = &buf[0]; would be equivalent
const char* pt2 = "hello";
strcpy(ptr, pt2);
printf("%s", ptr);
尽管这毫无意义,但是因为ptr
可以随处被buf
取代,并且可以删除ptr
:
char buf[8];
const char* pt2 = "hello";
strcpy(buf, pt2);
printf("%s", buf);
首先,您不知道如何使用strcpy
。 第一个参数需要指向可复制到的空间,它不会为您分配空间。
您的第一个示例可能仅“有效”,因为它正在复制到堆栈空间中。 这是未定义的行为,将导致各种问题。
您的第二个示例(更正确的示例)通常会导致段错误,因为您正试图复制到空地址(或从中读取)。
您需要为ptr变量(malloc)分配内存。 然后,有用的函数是strdup()。
它需要一个字符串,为新字符串分配良好的内存空间,并在返回新字符串之前复制其中的源内容。
你可以做:
ptr = strdup(pt2);
您正在写入随机存储器,这是未定义的行为。 这意味着根据C标准,允许编译器生成实际上可以执行任何操作的代码,包括但不限于:
打印“你好”。
打印随机乱码。
崩溃了
破坏了您应用中的其他变量。
在时空的结构上打一个洞,导致来自第五维度的邪恶的空间狐猴的入侵,由于供应过剩而破坏了Kopi Luwak咖啡的市场。
Tl; dr:不要那样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.