[英]What is the difference between using strcpy and equating the addresses of strings?
我无法理解strcpy函数和使用指针等效字符串地址的方法之间的区别。下面给出的代码将使我的问题更加清晰。 任何帮助,将不胜感激。
//code to take input of strings in an array of pointers
#include <stdio.h>
#include <strings.h>
int main()
{
//suppose the array of pointers is of 10 elements
char *strings[10],string[50],*p;
int length;
//proper method to take inputs:
for(i=0;i<10;i++)
{
scanf(" %49[^\n]",string);
length = strlen(string);
p = (char *)malloc(length+1);
strcpy(p,string);//why use strcpy here instead of p = string
strings[i] = p; //why use this long way instead of writing directly strcpy(strings[i],string) by first defining malloc for strings[i]
}
return 0;
}
关于指针魔力的简短介绍:
char *strings[10],string[50],*p;
这三个变量具有不同的类型:
char *strings[10]; // an array of 10 pointers to char
char string[50]; // an array of 50 char
char *p; // a pointer to char
然后完成以下(10次):
scanf(" %49[^\n]",string);
从输入读取C字符串并将其存储到string
考虑到0终止符也必须适合。
length = strlen(string);
计算非0字符,直到找到0终结符并存储length
。
p = (char *)malloc(length+1);
在堆上分配长度为+ 1(对于0终结符)的内存,并在p
存储该内存的地址。 ( malloc()
可能会失败。检查if (p != NULL)
不会受到伤害。)
strcpy(p,string);//why use strcpy here instead of p = string
在复制C字符串string
到内存中指出p
。 strcpy()
副本直到(包含)在源代码中找到0终止符。
strings[i] = p;
将p
(指向内存的指针)分配给strings[i]
。 (在赋值strings[i]
指向与p
相同的内存之后。赋值是一个指针赋值,但不指定指向的值。)
为什么strcpy(p,string);
而不是p = string
:
后者将string
地址(可能存储在堆栈中的局部变量)分配给p
。
已分配内存的地址(使用malloc()
)将丢失。 (这会引入内存泄漏 - 堆中的内存,代码中的任何指针都无法解决。)
p
现在将指向局部变量的string
(在每次迭代for
循环)。 因此,之后, strings[10]
所有条目最终将指向string
。
char *strings[10]---- --------->1.
strcpy(strings[i],string) ----->2.
strings[i] = string ----------->3.
p = (char *)malloc(length+1); -|
strcpy(p,string); |-> 4.
strings[i] = p;----------------|
strings
是一个指针数组,每个指针必须指向有效的内存。将导致未定义的行为,因为
strings[i]
没有指向有效的内存。- 可以工作但
strings
每个指针都指向相同的位置,因此每个指针都有相同的内容。- 因此,首先创建新内存,将内容复制到它并将该内存分配给
strings[i]
strcpy
将特定字符串复制到已分配的内存中。 分配指针实际上并不复制字符串,只是将第二个指针变量设置为与第一个相同的值。
strcpy(char *destination, char *source);
从源复制到目标,直到函数找到'\\ 0'。 此功能不安全,不应使用 - 请尝试使用strncpy
或strlcpy
。 您可以在https://linux.die.net/man/3/strncpy找到有关这两个功能的有用信息 - 检查代码的运行位置,以帮助您选择最佳选项。
在您的代码块中,您有此声明
char *strings[10],string[50],*p;
这声明了三个指针,但它们完全不同。 *p
是一个普通指针,必须先为它分配空间(通过malloc
)才能使用它。 string[50]
也是一个指针,但是长度为50(字符, 通常是 1个字节) - 并且它直接在函数堆栈上分配,因此你可以立即使用它(尽管它的第一次使用应该是将它清零内存,除非你使用了像Solaris的calloc
这样的归零分配器。最后, *strings[10]
是一个双指针 - 你已经分配了一个包含10个指针的数组,每个指针的每个元素( strings[1]
, strings[9]
等等) )必须在使用前分配。
您可以立即分配的唯一一个是string
,因为该空间已经分配。 这些指针中的每一个都可以通过下标来解决 - 但是在每种情况下,您必须确保不会走到最后,否则您将导致SIGSEGV“分段违规”,并且您的程序将崩溃。 或者至少,它应该,但你可能只会得到奇怪的结果。
最后,必须手动释放分配给的指针,否则你将有内存泄漏。 不需要释放在堆栈( string
)上分配的项目,因为编译器在函数结束时为您处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.