简体   繁体   English

是否使用strcpy

[英]To use strcpy or not

If I have an array of strings 如果我有一个字符串数组

char* q[2];
q[0] = "Hello";
q[1] = "World";

and I want to put q[0] in a new array of strings 我想把q[0]放在一个新的字符串数组中

char* x[2];

called x in x[0], should I use strcpy or just this? 在x [0]中调用x,我应该使用strcpy吗?

x[0] = q[0];

This seems to work, but no using strcpy has caused some problems in the past. 这似乎有效,但过去没有使用strcpy引起一些问题。

Should I do this just in case? 我是否应该这样做以防万一? What is the difference? 有什么区别?

char* a = malloc(strlen(q[0]) + 1);
strcpy(a, q[0]);
x[0] = a;

The assignment works without allocating any extra memory. 分配工作时不分配任何额外的内存。

If you use strcpy() , you have to assign enough memory to x[0] before you do the copy ( strlen(q[0]) + 1 bytes minimum), and you have to ensure it is released at the appropriate time. 如果使用strcpy() ,则必须在执行复制( strlen(q[0]) + 1最少strlen(q[0]) + 1个字节)之前为x[0]分配足够的内存,并且必须确保在适当的时间释放它。

To be clear, there is nothing "broken" about strcpy() ; 要清楚, strcpy()没有“破碎”; if it has "has caused some problems in the past" for you, that that is because of errors in your usage, not any intrinsic issue with strcpy() , and you should perhaps post a question about that so your misconceptions can be corrected. 如果它为你造成过去的某些问题” ,那是因为你的使用错误,而不是strcpy()任何内在问题,你应该发布一个问题,这样你的错误观念就可以得到纠正。

The semantics between string pointer assignment and string copy differ, so it depends what you are trying to do. 字符串指针赋值字符串复制之间的语义不同,因此它取决于您要执行的操作。

x is an array of pointers. x是一个指针数组。 The assignment: 分配:

x[0] = q[0];

Does not copy the string pointed to by q[0] to the memory pointed to by x[0] . q[0]指向的字符串复制到x[0]指向的内存中。 rather it changes the value of x[0] to the address of the string referred to by q[0] . 而是将x[0]的值更改为q[0]引用的字符串的地址。 So they both refer to the same string in memory. 所以他们都在内存中引用相同的字符串 No string data is moved or copied , only the reference to the string literals in this case: 没有移动复制字符串数据,在这种情况下只引用字符串文字:

q[0] --> "Hello"
          ^
          |
x[0] -----

In this sense x is not "a new array of strings" as you describe, but an array of pointers to the same strings . 从这个意义上说, x不是你所描述的“一个新的字符串数组” ,而是一个指向相同字符串的指针数组。 So is perhaps not the semantic behaviour you intended. 所以也许不是你想要的语义行为。

If you were to attempt: 如果您尝试:

strcpy( x[0], q[0] ) ;

That would be a semantic error since in your fragments x[0] does not point to any defined memory, so the string data referred to by q[0] will be copied to some undefined location with undefined results - none good, even if it superficially appears to work. 这将是一个语义错误,因为在你的片段中, x[0]没有指向任何已定义的内存,因此q[0]引用的字符串数据将被复制到某个未定义的位置,结果不确定 - 没有好处,即使它表面上似乎工作。

If x[0] referred to some validly allocated space by for example either being declared as an array thus: 如果x[0]引用一些有效分配的空间,例如要么被声明为数组,那么:

char x[2][128] ;

or being dynamically allocated: 或动态分配:

x[0] = malloc( 128 ) ;

or by first being assigned to some other valid space: 或者首先被分配到其他一些有效空间:

char a[120]
x[0] = a ;

Or by dynamically allocating a as in the example in your question. 或者通过动态地分配a在你的问题的例子。

Then strcpy( x[0], q[0] ) is a valid operation and would copy the string referred to by q[0] to the space referred to by x[0] : 然后strcpy( x[0], q[0] )是一个有效的操作,并将q[0]引用的字符串复制x[0]引用的空间:

q[0] --> "Hello"

x[0] --> "Hello"

Critically in this case the strings do not refer to the same space in memory. 在这种情况下,重要的是字符串不是指内存中的相同空间。

Note that if you actually wanted string pointer assignment semantics (which is probably less likely), and q refers to literal string constants , then for safer code it is important that you declare the arrays as pointers to const data: 请注意,如果您确实需要字符串指针赋值语义(可能不太可能),并且q引用文字字符串常量 ,那么对于更安全的代码,将数组声明为const数据的指针是很重要的:

const char* q[2] ;
const char* x[2] ;

The q array should be declared const in this case in any event, but clearly x should not be const if you want string-copy semantics. 在任何情况下, q数组都应该在这种情况下声明为const ,但如果你想要字符串复制语义,那么显然x不应该是const。

Helpfully by declaring it const , any attempt to strcpy() to it will fail deterministicly at compilation rather than having some undefined and erroneous and possibly latent run-time behaviour. 通过声明const来帮助它,任何strcpy()尝试都会在编译时确定性地失败,而不是有一些未定义和错误的,可能是潜在的运行时行为。 So it enforces the intended semantics if that is indeed what you intended. 因此,如果确实如此,它会强制执行预期的语义。 Equally it stops you from attempting to modify the data referred to by q[n] which would also be undefined behaviour (but will generally cause a runtime error on a modern desktop OS). 同样,它会阻止您尝试修改q[n]引用的数据,这也是未定义的行为(但通常会在现代桌面操作系统上导致运行时错误)。

There is no general rule, which one is better. 没有一般规则,哪一个更好。 This solely depends on your intented usage of the strings. 这完全取决于您对字符串的意图用法。

Simply assigning the pointer will work if you do not plan to modify the memory independently. 如果您不打算单独修改内存,只需指定指针即可。

If you free the first pointer, you will still have a copy in the second pointer. 如果释放第一个指针,您仍将在第二个指针中有一个副本。 But now it is invalid. 但现在它无效。 Also if you add or change content via one pointer, this change will be visible via second pointer as well. 此外,如果您通过一个指针添加或更改内容,则此更改也将通过第二个指针显示。 This happens because you are using same memory. 这是因为您使用相同的内存。

If you copy the string, you have independend content. 如果您复制字符串,则您拥有独立内容。 You can free or modify via the first pointer and still use it via second pointer. 您可以通过第一个指针释放或修改,并仍然通过第二个指针使用它。 Of course you also have to free the memory separately if you have copied to another location. 当然,如果您已复制到其他位置,则还必须单独释放内存。

The simple assignment is faster, of course. 当然,简单的任务更快。 Which one is better depends on your needs. 哪一个更好取决于您的需求。

I have an array of strings 我有一个字符串数组

Well, not quite. 嗯,不太好。 q is declared as q被声明为

char* q[2];

Which makes it an array of two pointers to char . 这使得它成为两个指向char指针的数组。 What is commonly referred to as a string , in C, is a NULL-terminated array of char . 在C中,通常称为字符串的是一个以NULL结尾的char数组。

Then, two values are assigned to each element of the array: 然后,为数组的每个元素分配两个值:

q[0] = "Hello";
q[1] = "World";

Where both "Hello" and "World" are string literals . "Hello""World"都是字符串文字 No string is copied here, only the pointers. 这里没有复制字符串,只有指针。

Later in the code you could reassign each pointer, like in 稍后在代码中你可以重新分配每个指针,就像在

q[0] = "Bye";

But any attempt to modify the characters or free the pointers would lead to hard to detect bugs. 但任何修改字符释放指针的尝试都会导致很难发现错误。

It would be safer to declare it as an array to pointer to const char , if they are meant to be untouched, so that, in case of mistakes, at least the error messages would be more informative. 将它声明为指向const char的数组会更安全,如果它们是不受影响的,那么在出错的情况下,至少错误消息会提供更多信息。 Eg 1 or 2 . 例如12

If you need modifiable strings and the control of those objects lifetime, your only option is to allocate enough memory and copy the strings. 如果您需要可修改的字符串并控制这些对象的生命周期,您唯一的选择是分配足够的内存并复制字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM