简体   繁体   English

我可以strupr工作但strcpy无法工作

[英]How is it that I can strupr work but strcpy does not

Here is my code. 这是我的代码。

int main()
{
struct emp
{
    char *n;
    int age;
};
struct emp e1 = {"Dravid", 23};
struct emp e2 = e1;
strupr(e2.n);
printf("%s\n", e1.n);
return 0;
}

Question 1: The answer as per the website is 'DRAVID' that is upper case. 问题1:根据网站的答案是大写的“ DRAVID”。 Howcome, are e2 and e1 same? 怎么了,e2和e1一样吗? ie if I do, e2.age++ then will this change be reflected in e1 too? 即如果我这样做,那么e2.age ++也会在e1中反映出来吗?

Question 2: If I change the strupr to strcpy I get seg fault? 问题2:如果将strupr更改为strcpy,则会出现段错误? Why? 为什么? ie If i change it to strcpy(e2.n,"hoho"); 即如果我将其更改为strcpy(e2.n,"hoho"); .

After you construct your two emp s, this is what you have in memory: 构建两个emp ,这就是您的内存:

e1.age  = 23
e1.name = 0x12345678 (Which is a pointer in memory to "Dravid")
e2.age  = 23
e2.name = 0x12345678 (Which is a pointer in memory to "Dravid")

Now notes, on what you're trying to do. 现在记下您要尝试执行的操作。

  1. Calling strupr(e1.name) is undefined behavior, because you're not allowed to modify string literals. 调用strupr(e1.name)是未定义的行为,因为不允许您修改字符串文字。
  2. Calling strcpy(e1.name, e2.name) is also undefined behavior, because strcpy requires that the two pointers passed to it refer to different pieces of memory. 调用strcpy(e1.name, e2.name)也是未定义的行为,因为strcpy要求传递给它的两个指针引用不同的内存。 Also, its UB because you can't modify string literals. 另外,它的UB是因为您不能修改字符串文字。
  3. Calling strcpy(e1.name, "hiho") is also undefined behavior, because you can't modify string literals. 调用strcpy(e1.name, "hiho")也是未定义的行为,因为您不能修改字符串文字。

1) Assigning a structure does a memberwise copy. 1)分配结构会进行成员复制。 Since n is a pointer, the pointer address is copied so it points to the same string. 由于n是指针,因此将复制指针地址,使其指向相同的字符串。

2) strcpy requires two arguments. 2) strcpy需要两个参数。 Remember that e2.n is a pointer. 记住e2.n是一个指针。 You must allocate sufficient space to that pointer to hold the contents of the new string when calling strcpy . 调用strcpy时,必须为该指针分配足够的空间以容纳新字符串的内容。 You are better off with strncpy() : 您最好使用strncpy()

int maxlen = 20;
e2.n = malloc(maxlen);
strncpy(e2.n, "Any length string here", maxlen - 1) /* only copies 19 bytes + terminating null */

When you copy a struct to another you copy all the values in the struct. 将一个结构复制到另一个结构时,将复制该结构中的所有值。 For age you just copy the value, so you can change it and they will differ. 对于年龄,您只需复制该值,即可更改它,它们将有所不同。

For n you are copying the address of the string so when you change one of the strings you also change the other. 对于n,您正在复制字符串的地址,因此,当您更改一个字符串时,也会更改另一个字符串。

And, as H2CO3 pointed out, you can't modify string literals which is what you attempt to do when using strcpy. 而且,正如H2CO3所指出的那样,您无法修改使用strcpy时要尝试执行的字符串文字。

Q1. Q1。 The char * n stores the address, which is copied, so if you change the value at the both will be reflected. char * n存储要复制的地址,因此,如果更改该值,则两者都会反映出来。

Q2. Q2。 strcpy() needs 2 parameters, can you show what did you code. strcpy()需要2个参数,您能否显示代码。

C, unlike Java, uses different memory areas for different variables. 与Java不同,C使用不同的内存区域存储不同的变量。 So when you assign one struct to another, it does what is basically a shallow copy of one area to another. 因此,当您将一个结构分配给另一个结构时,它基本上是将一个区域的浅表副本复制到另一个区域。 By shallow copy what I mean is that any pointers are not followed through to make clones of those so any pointers will point to the same place. 我所说的浅表复制是指没有遵循任何指针来对其进行克隆,因此任何指针都将指向同一位置。 It is just a copy of one memory area to another. 它只是一个存储区域到另一个存储区域的副本。

To say struct emp e2 = e1; 要说struct emp e2 = e1; is the same thing as to say memcpy (&e2, &e1, sizeof(struct emp)); 和说memcpy (&e2, &e1, sizeof(struct emp));是一样的东西memcpy (&e2, &e1, sizeof(struct emp));

This in turn means that if you assign a struct to another struct variable and then modify the data in the other struct variable, the first struct variable is not modified. 反过来这意味着,如果将一个结构分配给另一个结构变量,然后修改另一个结构变量中的数据,则第一个结构变量不会被修改。

So in C each variable is a different memory location where as with Java and some other languages you are working with variable references and the variable names are just containers for the variable reference (except for built in primitives like int). 因此,在C语言中,每个变量都是一个不同的内存位置,就像Java和其他一些语言一样,您在其中使用变量引用,并且变量名称只是变量引用的容器(除了内置原语(如int))。

You have a bit of a possible problem with your code in that you are using a constant string. 您的代码可能存在一些问题,因为您使用的是常量字符串。 It is not good to modify a constant string as you are doing with strupr() because you do not know how the memory is allocated or where it is allocated. 像使用strupr()那样修改常量字符串是不好的,因为您不知道内存是如何分配的或在哪里分配的。 So with doing a strupr() you are basically getting lucky. 因此,通过执行strupr(),您基本上会很幸运。

See this about difference between a deep copy and a shallow copy . 有关深层副本和浅层副本之间的区别,请参见此内容。

They should not be the same after the call to strupr (but it's not safe or proper to modify a string literal anyway). 在调用strupr之后,它们应该不相同(但是修改字符串文字既不安全也不适当)。 And no, a change to e2 will not be reflected in e1 because the assignment will copy the object by value. 不,对e2的更改将不会反映在e1因为赋值将按值复制对象。

As for changing the strupr call to strcpy, strcpy takes two arguments, so just changing it will cause a compilation error. 至于将strupr调用更改为strcpy,strcpy需要两个参数,因此仅对其进行更改将导致编译错误。 If you add e1.n as the second argument, it will crash because e2.n hasn't been initialized to point to any memory. 如果将e1.n添加为第二个参数,它将崩溃,因为e2.n尚未初始化为指向任何内存。

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

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