如果我有一个字符串数组
char* q[2];
q[0] = "Hello";
q[1] = "World";
我想将q[0]
放入新的字符串数组中
char* x[2];
在x [0]中称为x,我应该使用strcpy还是这样?
x[0] = q[0];
这似乎可行,但是过去没有使用strcpy会引起一些问题。
我是否应该这样做以防万一?有什么区别?
char* a = malloc(strlen(q[0]) + 1);
strcpy(a, q[0]);
x[0] = a;
答案 0 :(得分:4)
该分配工作而不会分配任何额外的内存。
如果使用strcpy()
,则必须在复制之前为x[0]
分配足够的内存(最少strlen(q[0]) + 1
个字节),并且必须确保在适当的位置释放它时间。
答案 1 :(得分:3)
需要明确的是,strcpy()
并没有“坏处”;如果它为您“过去曾引起一些问题” ,那是因为使用错误,而不是strcpy()
的任何内在问题,您应该发布一个问题可以解决您的误解。
字符串指针分配和字符串副本之间的语义不同,因此这取决于您要执行的操作。
x
是一个指针数组。作业:
x[0] = q[0];
不是否将q[0]
指向的字符串复制到x[0]
指向的内存。而是将x[0]
的值更改为q[0]
所引用的字符串的地址。因此它们都引用内存中的相同字符串。不会移动或复制任何字符串数据,在这种情况下,仅引用字符串文字:
q[0] --> "Hello"
^
|
x[0] -----
从这个意义上讲,x
不是您所描述的“新的字符串数组” ,而是指向相同字符串的指针数组。所以也许不是您想要的语义行为。
如果要尝试:
strcpy( x[0], q[0] ) ;
这将是一个语义错误,因为在您的片段x[0]
中没有指向任何已定义的内存,因此q[0]
所引用的字符串数据将被复制不确定的位置会产生不确定的结果-不好,即使表面看来可以正常工作。
如果x[0]
引用了一些有效分配的空间,例如被声明为数组,则这样:
char x[2][128] ;
或正在动态分配:
x[0] = malloc( 128 ) ;
或首先分配给其他有效空间:
char a[120]
x[0] = a ;
或者通过动态分配a
来解决问题中的示例。
然后strcpy( x[0], q[0] )
是有效操作,并且会将q[0]
所指的字符串复制到x[0]
所指的空间:
q[0] --> "Hello"
x[0] --> "Hello"
在这种情况下,关键的是字符串不指向内存中的同一空间。
请注意,如果您实际上想要字符串指针分配语义(可能可能性较小),并且q
引用文字字符串常量,那么出于安全考虑代码很重要,您必须将数组声明为指向const
数据的指针:
const char* q[2] ;
const char* x[2] ;
在任何情况下,q
数组在任何情况下都应声明为const
,但显然,如果需要 string-copy 语义,x
不应为const 。
通过声明为const
,strcpy()
的任何尝试都将在编译时确定性地失败,而不是具有一些未定义的,错误的和潜在的运行时行为。因此,如果确实符合您的意图,它将强制执行预期的语义。同样,它使您无法尝试修改q[n]
所引用的数据,这也是未定义的行为(但通常会在现代台式机操作系统上导致运行时错误)。
答案 2 :(得分:1)
没有一般规则,哪个更好。这完全取决于您打算使用的字符串。
如果您不打算独立修改内存,则只需分配指针即可。
如果释放第一个指针,则第二个指针中仍将有一个副本。但是现在它是无效的。同样,如果您通过一个指针添加或更改内容,则此更改也将通过第二个指针可见。发生这种情况是因为您使用的是相同的内存。
如果复制字符串,则具有独立内容。您可以通过第一个指针释放或修改,但仍然可以通过第二个指针使用它。 当然,如果您已复制到另一个位置,则还必须分别释放内存。
简单的分配当然更快。 哪个更好取决于您的需求。
答案 3 :(得分:1)
我有一个字符串数组
嗯,不完全是。 q
被声明为
char* q[2];
这使它成为指向char
的两个指针的数组。在C中,通常称为 string 的是char
的以NULL结尾的数组。
然后,将两个值分配给数组的每个元素:
q[0] = "Hello";
q[1] = "World";
"Hello"
和"World"
均为字符串文字。这里没有字符串被复制,只有指针被复制了。
稍后,您可以在代码中重新分配每个指针,例如
q[0] = "Bye";
但是尝试进行modify the characters或free the pointers都会导致难以检测到错误。
将其声明为指向 const char
的指针的数组将是更安全的,如果它们本意是未被触动的,那么在出现错误的情况下,至少是错误消息会提供更多信息。例如1或2。
如果您需要可修改的字符串并控制这些对象的生存期,则唯一的选择是分配足够的内存并复制字符串。