strcpy的C实现不会改变变量值 [英] C implementention of strcpy does not change variable value

查看:237
本文介绍了strcpy的C实现不会改变变量值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我正试图实现我自己的strcpy,以便更好地理解指针在C中的工作方式,到目前为止我感到茫然。我尝试了很多不同的方法,尝试使用网络中的代码,以便稍后可以使用我的代码,但即使那些代码也不会工作。

我相信我可能会在主要方法上以错误的方式调用函数。我将该变量的指针传递给该函数,以便该函数可以更改该变量的值,并在函数调用时指定该指针的地址,以便该方法可以获取正确的数据。至少我相信这是它是如何工作的,无论如何我都能理解。



以下是函数和方法调用:

函数调用:

  void my_strcpy(char * dest,const char * src){

dest = malloc(sizeof(src));

while(src!='\0'){
* dest = * src;
src ++;
dest ++;
}

}

Main:

  int main(){

const char * s =Hello World;
char * test ='d';

my_strcpy(& test,& s); //将测试表单d更改为Hello World。
printf(Changed String:);
printf(%c,test);


return 0;

PS:我尝试使用测试作为比s更大的字符串来查看它是否是一个内存分配问题,但似乎并非如此。任何帮助都非常令人厌恶,因为我一直坚持了几个小时......



PS:我已经研究了如何更改变量的问题和示例以及可以使用简单的int来完成。但使用char *时我无法做到。因此,职位。我很抱歉,如果问题是相同的,但我不明白我在这里做错了什么。请耐心等待,因为我是C语言的初学者。 关键是,参数已通过传递按价值 in C。



最后,你的 my_strcpy 的行为不像标准的 strcpy (它不使用 malloc 分配内存)。由于 sizeof(src)总是 sizeof(char),因此 malloc 的使用是错误的*)(即在Linux / x86-64上为8)。



这是一个更好的版本:

  void my_strcpy(char * dest,const char * src){
while(* src!='\0'){
* dest = * src;
src ++;
dest ++;
}
* dest ='\0'; //零终止字符串
}

注意 strcpy (和 my_strcpy )本质上是危险的,因为您可能有缓冲区溢出(所以更经常使用 strncpy )。一个典型的用例是:

  char buf [80]; 
my_strcpy(buf,你好,我在这里);

所以我们有本地内存(通常在调用堆栈上),然后复制到内存中。如果文字字符串很长(例如超过80个字符),我们会有缓冲区溢出。

顺便说一句,您的测试 while(src!='\0')是非常错误的。指针与指向的值不同。您的错误测试通常会在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_FAILURE); };
strcpy(newptr,src);
返回newptr;
}

这有点像标准 strdup code>,除了我捕捉到内存不足的错误情况(当 malloc 失败时)。通常只显示一些错误消息并退出该失败的案例,但您应始终 处理 malloc 失败



详细了解 C动态内存管理记录您的记忆约定(当有一个函数通过 malloc calloc 等等......你需要记录谁是负责释放它以及如何)



害怕未定义行为内存泄漏。如果有的话,请使用 valgrind



阅读更多关于<垃圾收集(这是一个非常有用的术语和概念)。您可能想使用 Boehm保守垃圾收集器编写一些C程序(但使用Boehm的GC是一个完整的程序您的主要

  my_strcpy(& test,& s); //非常坏

多次错误(未定义行为,因为缓冲区溢出)。你应该传递一个能够包含字符串的内存区的地址(包括它的终止零字节),而第二个参数没有正确的类型(& s 是一个 char ** 不是一个 const char * )。


So, i am trying to implement my own strcpy to have a better understanding of how pointers work in C, and so far i am at a loss. I tried a lot of different approaches, tried using code from the net to maybe base mine on later, but even those wont work.

I believe i might be calling the function in the wrong way on the main method. I am passing a pointer of the variable to the function, so that the function can change the value of the variable and on the function call, i am giving the adress of the pointer so the method can get the correct data. At least i believe this is how it works, from what i could understand at any rate.

Here are the functions and the method calls:

Function call:

void my_strcpy( char *dest, const char* src ) {

dest = malloc(sizeof(src));

while ( src != '\0' ) {
  *dest = *src;
  src++;
  dest++;
 }

}

Main:

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: I tried using test as a string bigger than s to see if it was a memory allocation problem but it does not appear to be so. Any help is greatly apreciated as i have been stuck in this for hours...

PS: I've looked into the question and examples of how to change the variable and can do it using a simple int. But i cannot do it when using char*. Hence the post. I apologize if the issue is the same but i just cannot understand what i'm doing wrong here. Please, have patience with me as i am a beginner in C.

解决方案

The key point is that arguments are passed by value in C.

Hence any change of a formal argument is never seen by the caller function.

At last, your my_strcpy is not behaving like the standard strcpy (which does not allocate memory using malloc). And your use of malloc is wrong, since sizeof(src) is always sizeof(char*) (i.e. 8 on Linux/x86-64).

Here is a better version:

 void my_strcpy( char *dest, const char* src ) {
   while ( *src != '\0' ) {
     *dest = *src;
     src++;
     dest++;
   }
   *dest = '\0'; // zero terminate the string
 }

Notice that strcpy (and my_strcpy) is intrinsically dangerous because you may have buffer overflow (so use strncpy more often). A typical use case would be

 char buf[80];
 my_strcpy(buf, "hello I am here");

so we have local memory (on the call stack typically) and we copy into it. If the literal string was very long (e.g. more than 80 characters) we would have a buffer overflow.

BTW, your test while(src != '\0') was very wrong. A pointer is not the same the pointed value. Your wrong test would typically loop a billion times on a 32 bits machine and would crash before reaching the terminating condition src == NULL

Also in practice strcpy is often known by optimizing compilers like GCC which may even generate a loop, not a function call to a standard function, when compiling it.

Several of your mistakes would probably have been spotted by your compiler (e.g. GCC) if you enable all warnings in your compiler (which you always should), so compile e.g. with gcc -Wall -Wextra -g (to get all warnings, some more, and debug information) then use the debugger gdb to run your program step by step.

In practice, when possible, have functions returning pointers, like

 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;
 }

this is a bit like the standard strdup except that I am catching the out-of-memory error case (when malloc fails). It is common to just show some error message and exit in that failing case, but you should always handle malloc failure

Read more about C dynamic memory management and document your memory conventions (when having a function allocating memory in heap thru malloc or calloc etc... you need to document who is in charge of freeing it and how).

Be afraid of undefined behavior and of memory leaks. Use valgrind if available.

Read a bit more about garbage collection (it is a very useful terminology and concept). You might want to code some C programs using Boehm conservative garbage collector (but using Boehm's GC is a whole program decision).

In your main

 my_strcpy( &test, &s ); // VERY BAD

is many times wrong (undefined behavior because of buffer overflow). You should pass an address of a memory zone able to contain the string (including its terminating zero byte), and the second argument does not have the right type (&s is a char** not a const char*).

这篇关于strcpy的C实现不会改变变量值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆