strcpy 的 C 实现不会改变变量值
C implementention of strcpy does not change variable value
所以,我正在尝试实现我自己的 strcpy 以更好地理解指针在 C 中的工作方式,但到目前为止我还是一头雾水。我尝试了很多不同的方法,尝试过使用来自网络的代码,也许以后会以我的代码为基础,但即使是那些也行不通。
我相信我可能在 main 方法上以错误的方式调用了函数。我将变量的指针传递给函数,以便函数可以更改变量的值,并且在函数调用时,我给出了指针的地址,以便该方法可以获得正确的数据。至少我相信这就是它的工作原理,无论如何我可以理解。
函数和方法调用如下:
函数调用:
void my_strcpy( char *dest, const char* src ) {
dest = malloc(sizeof(src));
while ( src != '[=10=]' ) {
*dest = *src;
src++;
dest++;
}
}
主要:
int main () {
const char* s = "Hello World";
char* test = 'd';
my_strcpy( &test, &s ); // Suposed to change test form d to Hello World.
printf("Changed String: " );
printf( "%c", test );
return 0;
}
PS:我试过用test作为一个比s大的字符串,看是不是内存分配的问题,但好像不是。非常感谢任何帮助,因为我已经坚持了几个小时...
PS:我研究了如何更改变量的问题和示例,并且可以使用简单的 int 来完成。但是在使用 char* 时我做不到。因此 post。如果问题相同,我深表歉意,但我无法理解我在这里做错了什么。请耐心等待我,因为我是 C 语言的初学者。
关键是参数在C中传递by value
因此调用函数永远不会看到形式参数的任何更改。
最后,您的 my_strcpy
与标准 strcpy
的行为不同(它不使用 malloc
分配内存)。而且您对 malloc
的使用是错误的,因为 sizeof(src)
始终是 sizeof(char*)
(即 Linux/x86-64 上的 8)。
这是一个更好的版本:
void my_strcpy( char *dest, const char* src ) {
while ( *src != '[=10=]' ) {
*dest = *src;
src++;
dest++;
}
*dest = '[=10=]'; // zero terminate the string
}
请注意 strcpy
(和 my_strcpy
)本质上是危险的,因为您可能有 buffer overflow(所以更经常使用 strncpy
)。一个典型的用例是
char buf[80];
my_strcpy(buf, "hello I am here");
所以我们有本地内存(通常在调用堆栈上),我们将其复制到其中。如果文字字符串很长(例如超过 80 个字符),我们就会发生缓冲区溢出。
顺便说一句,你的测试 while(src != '[=23=]')
非常错误。指针与指向的值不同。您的错误测试通常会在 32 位机器上循环十亿次,并且会在达到终止条件 src == NULL
之前崩溃
在实践中,strcpy
通常通过优化编译器而为人所知,例如 GCC,编译时甚至可能生成循环,而不是对标准函数的函数调用。
如果你在你的编译器中启用所有警告(你总是应该),你的编译器可能会发现你的一些错误(例如GCC),所以编译例如使用 gcc -Wall -Wextra -g
(获取所有警告、更多警告和调试信息)然后使用调试器 gdb
逐步 运行 您的程序。
在实践中,如果可能的话,有函数返回指针,比如
char* my_almost_strdup(const char*src) {
size_t ln = strlen(src);
char* newptr = malloc(ln+1);
if (!newptr) { perror("my_strdup"); exit(EXIT_FAILURE); };
strcpy (newptr, src);
return newptr;
}
这有点像标准的 strdup
,只是我正在捕获内存不足的错误情况(当 malloc
失败时)。在失败的情况下只显示一些错误消息并退出是很常见的,但是你应该 always handle malloc
failure
阅读更多关于 C dynamic memory management 和 记录您的 内存 约定 (当函数通过 malloc
或 calloc
等...您需要记录谁负责释放它以及如何释放它)。
如果有就怕undefined behavior and of memory leaks. Use valgrind
阅读更多关于 garbage collection (it is a very useful terminology and concept). You might want to code some C programs using Boehm conservative garbage collector 的信息(但使用 Boehm 的 GC 是整个程序的决定)。
在你的main
my_strcpy( &test, &s ); // VERY BAD
多次 错误 (由于缓冲区溢出导致的未定义行为)。您应该传递能够包含字符串(包括其终止零字节)的内存区域的地址,并且第二个参数没有正确的类型(&s
是 char**
而不是 const char*
).
你不需要 & 来引用 char *
因为它已经是一个指向字符的指针,你不需要 char **
这是一个指向字符指针的指针.
我修补了它:
void my_strcpy(char** dest, const char* src) {
const char * srcTemp = src;
int i = 1; //+1 for null char
while (*srcTemp != '[=10=]') {
srcTemp++;
i++;
}
char * destTemp = (char*)malloc(sizeof(char)*i);
*dest = destTemp;
while (*src != '[=10=]') {
*destTemp = *src;
src++;
*destTemp++;
}
*destTemp = *src; //copy null char
}
int _tmain(int argc, _TCHAR* argv[])
{
const char* s = "Hello World";
char* test = 0;
my_strcpy(&test, s); // Suposed to change test form d to Hello World.
printf("Changed String: ");
printf("%s", test);
return 0;
}
所以,我正在尝试实现我自己的 strcpy 以更好地理解指针在 C 中的工作方式,但到目前为止我还是一头雾水。我尝试了很多不同的方法,尝试过使用来自网络的代码,也许以后会以我的代码为基础,但即使是那些也行不通。
我相信我可能在 main 方法上以错误的方式调用了函数。我将变量的指针传递给函数,以便函数可以更改变量的值,并且在函数调用时,我给出了指针的地址,以便该方法可以获得正确的数据。至少我相信这就是它的工作原理,无论如何我可以理解。
函数和方法调用如下:
函数调用:
void my_strcpy( char *dest, const char* src ) {
dest = malloc(sizeof(src));
while ( src != '[=10=]' ) {
*dest = *src;
src++;
dest++;
}
}
主要:
int main () {
const char* s = "Hello World";
char* test = 'd';
my_strcpy( &test, &s ); // Suposed to change test form d to Hello World.
printf("Changed String: " );
printf( "%c", test );
return 0;
}
PS:我试过用test作为一个比s大的字符串,看是不是内存分配的问题,但好像不是。非常感谢任何帮助,因为我已经坚持了几个小时...
PS:我研究了如何更改变量的问题和示例,并且可以使用简单的 int 来完成。但是在使用 char* 时我做不到。因此 post。如果问题相同,我深表歉意,但我无法理解我在这里做错了什么。请耐心等待我,因为我是 C 语言的初学者。
关键是参数在C中传递by value
因此调用函数永远不会看到形式参数的任何更改。
最后,您的 my_strcpy
与标准 strcpy
的行为不同(它不使用 malloc
分配内存)。而且您对 malloc
的使用是错误的,因为 sizeof(src)
始终是 sizeof(char*)
(即 Linux/x86-64 上的 8)。
这是一个更好的版本:
void my_strcpy( char *dest, const char* src ) {
while ( *src != '[=10=]' ) {
*dest = *src;
src++;
dest++;
}
*dest = '[=10=]'; // zero terminate the string
}
请注意 strcpy
(和 my_strcpy
)本质上是危险的,因为您可能有 buffer overflow(所以更经常使用 strncpy
)。一个典型的用例是
char buf[80];
my_strcpy(buf, "hello I am here");
所以我们有本地内存(通常在调用堆栈上),我们将其复制到其中。如果文字字符串很长(例如超过 80 个字符),我们就会发生缓冲区溢出。
顺便说一句,你的测试 while(src != '[=23=]')
非常错误。指针与指向的值不同。您的错误测试通常会在 32 位机器上循环十亿次,并且会在达到终止条件 src == NULL
在实践中,strcpy
通常通过优化编译器而为人所知,例如 GCC,编译时甚至可能生成循环,而不是对标准函数的函数调用。
如果你在你的编译器中启用所有警告(你总是应该),你的编译器可能会发现你的一些错误(例如GCC),所以编译例如使用 gcc -Wall -Wextra -g
(获取所有警告、更多警告和调试信息)然后使用调试器 gdb
逐步 运行 您的程序。
在实践中,如果可能的话,有函数返回指针,比如
char* my_almost_strdup(const char*src) {
size_t ln = strlen(src);
char* newptr = malloc(ln+1);
if (!newptr) { perror("my_strdup"); exit(EXIT_FAILURE); };
strcpy (newptr, src);
return newptr;
}
这有点像标准的 strdup
,只是我正在捕获内存不足的错误情况(当 malloc
失败时)。在失败的情况下只显示一些错误消息并退出是很常见的,但是你应该 always handle malloc
failure
阅读更多关于 C dynamic memory management 和 记录您的 内存 约定 (当函数通过 malloc
或 calloc
等...您需要记录谁负责释放它以及如何释放它)。
如果有就怕undefined behavior and of memory leaks. Use valgrind
阅读更多关于 garbage collection (it is a very useful terminology and concept). You might want to code some C programs using Boehm conservative garbage collector 的信息(但使用 Boehm 的 GC 是整个程序的决定)。
在你的main
my_strcpy( &test, &s ); // VERY BAD
多次 错误 (由于缓冲区溢出导致的未定义行为)。您应该传递能够包含字符串(包括其终止零字节)的内存区域的地址,并且第二个参数没有正确的类型(&s
是 char**
而不是 const char*
).
你不需要 & 来引用 char *
因为它已经是一个指向字符的指针,你不需要 char **
这是一个指向字符指针的指针.
我修补了它:
void my_strcpy(char** dest, const char* src) {
const char * srcTemp = src;
int i = 1; //+1 for null char
while (*srcTemp != '[=10=]') {
srcTemp++;
i++;
}
char * destTemp = (char*)malloc(sizeof(char)*i);
*dest = destTemp;
while (*src != '[=10=]') {
*destTemp = *src;
src++;
*destTemp++;
}
*destTemp = *src; //copy null char
}
int _tmain(int argc, _TCHAR* argv[])
{
const char* s = "Hello World";
char* test = 0;
my_strcpy(&test, s); // Suposed to change test form d to Hello World.
printf("Changed String: ");
printf("%s", test);
return 0;
}