我对 C 中按值复制/按引用复制的理解是否正确?

is my understanding of copying by value / copying by reference in C correct?

以下是我认为 C 代码执行的工作原理:

给定代码块中使用的变量映射包含对:

identifier: <address in memory where the value of a given type is located (its first byte)>

当一个块结束并自动释放内存时,它们将被丢弃(但我们自己分配的内存不会被释放)。

如果分配给其他标识符,它们的值总是被复制。例如,下面我们在 t1 中有一个结构分配给 t2。值被复制,我们现在有两个完全相同的对象(t2 存储了 t1 的副本)。改变一个不会改变另一个。这与 javascript 不同,其中 t1 = t2 总是导致 t1 并且 t2 指向内存中的相同位置。

typedef struct _thing 
{ 
    char item;
    char item2;
} THING;

int main (void) {
  THING t1;
  t1.item = 'a';
  t1.item2 = 'b';
  THING t2 = t1;
  t2.item = 'c';
  if (t1.item == 'a') {
    printf("t1.item is a");
  }
}

下面,我们将引用(值开始的内存位置)复制到 t2 中的 t1。标识符 t2 映射到存储在 t1 中的对象的内存地址开始的内存地址。 &t1 == t2&t1 != &t2;

int main (void) {
  THING t1;
  t1.item = 'a';
  t1.item2 = 'b';
  THING* t2 = &t1;
  t2->item = 'c';
  if (t1.item == 'c') {
    printf("item is c");
  }
}

最后,最后一个示例展示了如何像 javascript 中处理对象一样处理对象,其中非基本对象始终通过引用传递:

int main (void) {
  THING* t1;
  THING* t2;
  t1 = (THING *) malloc (sizeof(THING));
  t1->item = 'a';
  t1->item2 = 'b';
  t2 = t1;
  t2->item = 'c';
  if (t1->item == 'c') {
    printf("item is c");
  }
  free(t1);
}

这里要明确的说,t1t2存储指针(*)。此外,我们必须使用箭头符号 (->) 而不是点符号 (.) 和手动 allocate/free 内存。

这是正确的吗?

Here's how I think a C code execution works:

There's a map of variables used in a given code block that contains pairs:

从 "as if" 的意义上说,也许。真实世界的 C 实现没有您描述的文字映射。事实上,变量的标识符通常在运行时根本不可用。在程序运行之前,它们在编译和/或 link 时被解析为地址。

They are discarded when a block ends and memory is automatically freed (but memory that we allocated ourselves is not released).

自动分配的对象的生命周期在其标识符超出范围时结束。这可能与您用术语 "discarded".

描述的含义和含义完全相同,也可能不完全相同。

Their values are always copied if assigned to other identifiers.

是的,赋值是一个复制操作。但是在这个特定问题的上下文中,重要的是要了解复制(分配)的值是什么。特别是,指针是 C 中的 first-class 对象,与它们指向的对象(如果有)不同。将指针值分配给不同的指针与将一个指向对象的值分配给另一个指向对象是完全不同的操作。

For example, below we have a structure in t1 that is assigned to t2. The values are copied and we now have two exact objects (t2 stores a copy of t1). Changing one doesn't change the other. This is different from i.e. javascript where t1 = t2 would always lead to t1 and t2 point to the same location in memory.

是的,在 C 中,具有结构类型的对象可以直接访问,并且分配给一个对象本身会修改对象本身。但是请注意,这样的赋值操作是浅层的,因为当任何结构成员是指针时,指针被复制,留下该成员原始结构对应成员的别名结构。

Below, we have copied reference (memory location where a value starts) to t1 in t2. [...]

此时我注意到 C 没有 "references"。它有 指针 ,其值代表地址。这是一个非常相似的概念,但并不完全相同。

然而,无论如何,您对寻址运算符 & 和指针赋值的理解似乎是正确的。

Finally, the last example shows how to handle objects similarly to how they are treated in javascript where non-primitive objects are always passed by reference:

您的示例显示了一种创建指向结构对象的指针的方法,而无需声明对象本身(从而使其自动分配并与其自己的标识符相关联)。但是请注意,虽然这让人联想到 Javascript 中通过引用处理对象,但它与 pass by reference 关系不大,后者是关于调用函数/调用方法.

C(与 C++ 不同)没有传递引用。 C 函数调用总是按值传递,但传递的值可以是指针。据我了解,这类似于 Javascript,它也只有按值传递(传递的值可以是引用)。