[英]Assignment confusion in C
我是 C 新手,所以我需要一些帮助。
例如我有这个结构对象
struct Frac {
int num;
int dec
}
我在 c 中这样做:
struct Frac fract1 = {1, 2};
struct Frac temp;
temp = fract1;
temp 是指向 fract1 的副本还是指向实际的 fract1? 我通过打印地址在计算机上进行了尝试,它指向 fract1 的副本。 如果这是在 Java 中,它将指向实际的 fract1。 如果我错了,请纠正我。 我能问一下为什么 temp 指向 C 中 fract1 的副本而不是实际对象本身,谢谢!
没有任何东西指向任何东西。 赋值复制值。 赋值总是复制值。 有时这些值是指针,但如果您没有看到指针,则说明没有指针。 C 没有 Java 在具有值语义的简单类型和具有引用语义的所有其他类型之间的二分法。
“
temp
是指向fract1
的副本还是指向实际的fract1
”?
首先, temp
和fract1
不是指针。 有结构的对象类型。
frac1
的内容被复制到temp
但temp
是一个不同的对象。
temp 是指向 fract1 的副本还是指向实际的 fract1? 我通过打印地址在计算机上进行了尝试,它指向 fract1 的副本。
你是对的。 它将指向 fract1 的副本。
如果这是在 Java 中,它将指向实际的 fract1。
你是对的,在 Java 中会有两个对同一个对象的引用。
我可以问为什么 temp 指向 C 中 fract1 的副本而不是实际对象本身
C 不会自动在堆上分配对象,除非你要求它。 您可以通过使用指针和堆分配来重现类似于 Java 的内容。 但请注意,与 Java 不同,您需要明确地释放对象。
struct Fraction *frac1 = malloc(sizeof(struct Fraction));
frac1->num = 1;
frac1->dec = 2;
struct Fraction *temp;
temp = frac1;
// Both frac1 and temp point to the same object
...
// Make sure you free the object eventually
free(frac1);
是的,赋值运算符总是创建一个副本。 这是您通常所期望的。 Java 行为实际上是异常行为。
例如在 C 或 Java 中,
int a = 3;
int b = a;
你会想到b
,以点到“实际” a
或将b
是副本a
包含相同的值3
? 与 Java 不同,这正是 C 所做的,即使对于结构也是如此。 对于所有非平凡对象,Java 会在堆上隐式分配内存并创建一个引用(相当于一个指针)。 您在 Java 中所说的“对象”实际上是对对象的引用,当您使用赋值运算符复制它时,您实际上是在复制此引用。 在 C 中可以在堆栈上分配复合对象在 Java 等语言中是不可能的。
如果你想创建一个引用,你仍然可以使用 C 中的指针来做到这一点。你必须“取消引用”这个指针才能实际检索它后面的对象。
修改您的原始示例:
struct Frac fract1 = {1, 2};
struct Frac *temp;
struct Frac *temp2;
temp = &fract1; // Now temp points to the original fract1
temp2 = temp; // Copying a reference: temp2 is a copy of temp but both point to the same fract1
temp->num = 3; // This modifies fract1 indirectly
frac1
和temp
都是变量。 这些变量在内存中占据两个不同的空间。
C 中发生的事情是temp = frac1
正在将名为frac1
的内存的内容复制到名为temp
的内存中。
如果您正在处理指针,则内存中的空间和复制内容的这些想法仍然适用。
例如:
int *p;
- 内存中有一个名为 p 的空间; 然而,内存中这个空间的内容包含一个地址。 该地址又(可能)指代内存中的不同空间。 因此p = ...
将更新 p (它是一个指针)的内容,使其指向某个新的地方。 同时*p = ...
更改p
的内容指向的内存的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.