мое понимание копирования по значению / копирование по ссылке в C правильно? - PullRequest
0 голосов
/ 04 сентября 2018

Вот как я думаю, что выполнение кода на 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");
  }
}

Ниже мы скопировали ссылку (область памяти, где начинается значение) в t1 в t2. Идентификатор 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);
}

Здесь мы должны явно сказать, что t1 и t2 хранят указатели (*). Также мы должны использовать стрелочную нотацию (->) вместо точечной нотации (.) и выделять / освобождать память вручную.

Это правильно?

1 Ответ

0 голосов
/ 04 сентября 2018

Вот как я думаю, что выполнение кода C работает:

В данном блоке кода есть карта переменных, которая содержит пары:

В смысле «как будто», возможно. Реальные реализации C не имеют буквальных карт, таких как вы описали. Фактически, идентификаторы переменных вообще не доступны во время выполнения вообще. Они разрешаются по адресам во время компиляции и / или компоновки перед запуском программы.

Они отбрасываются, когда заканчивается блок и память автоматически освобождается (но память, которую мы сами себе выделили, не освобождается).

Время жизни автоматически распределенных объектов заканчивается в точке, где их идентификаторы выходят за пределы области видимости. Это может иметь или не иметь точно такое же значение и значение, как те, которые вы описываете термином «отброшено».

Их значения всегда копируются, если присвоены другим идентификаторам.

Да, присвоение является операцией копирования. Но в контексте этого конкретного вопроса важно понимать, какое значение копируется (присваивается). В частности, указатели являются первоклассными объектами в C, отличными от объектов, если таковые имеются, на которые они указывают. Присвоение значения указателя другому указателю является совершенно иной операцией, чем присвоение значения одного объекта, на который указывает точка, другому объекту, на который указывает указатель.

Например, ниже у нас есть структура в t1, которая назначена на t2. Значения копируются, и теперь у нас есть два точных объекта (t2 хранит копию t1). Изменение одного не меняет другого. Это отличается от, например, JavaScript, где t1 = t2 всегда будет приводить к t1 и t2, указывающим на одно и то же место в памяти.

Да, в C объекты, имеющие тип структуры, доступны напрямую, а присвоение одному из них изменяет сам объект. Но обратите внимание, что такая операция присваивания является мелкой, в том смысле, что, когда любой из элементов структуры является указателем, указатель копируется, оставляя этому члену псевдоним соответствующего члена исходной структуры.

Ниже мы скопировали ссылку (область памяти, где начинается значение) в t1 в t2. [...]

Я отмечаю, что у C нет «ссылок». Он имеет указателей , значения которых представляют адреса. Это очень похожая концепция, но не идентичная.

В любом случае, однако, ваше понимание оператора адреса & и назначения указателя представляется правильным.

Наконец, последний пример показывает, как обрабатывать объекты аналогично тому, как они обрабатываются в javascript, когда не примитивные объекты всегда передаются по ссылке:

В вашем примере показан способ создания указателя на объект структуры без объявления самого объекта (и, следовательно, его выделения автоматически и связывания с его собственным идентификатором). Однако, обратите внимание, что хотя это напоминает обработку объектов посредством ссылок в Javascript, это не имеет ничего общего с передачей по ссылке , которая касается вызова функций / вызова методов.

C (в отличие от C ++) не имеет передачи по ссылке. Вызовы функций C всегда передаются по значению, но передаваемые значения могут быть указателями. Насколько я понимаю, это аналог Javascript, который также имеет только передачу по значению (где передаваемые значения могут быть ссылками).

...