Объявление и назначение массива C?

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

Допустим, у меня есть два массива:

int x[10];  
int y[10];  

Почему x = y не компилируется? Если это одна и та же «подпись», то разве вы не должны иметь возможность назначать их туда и обратно?

Могу ли я объявить их таким образом, чтобы это позволило мне сделать это на C? Мне кажется логичным, что вы могли бы это сделать, но, может быть, есть способ, которым это можно сделать? Типовые определения для структур, казалось, были решением, будет ли это то же самое для объявления и присваивания массива?

Я ценю вашу помощь, я новичок в Stackoverflow, но до сих пор это был действительно хороший ресурс для меня!


person Mithrax    schedule 13.04.2009    source источник


Ответы (7)


Проще говоря, массивы не присваиваются. Это «неизменяемое значение». Конечно, возникает вопрос: почему? Пожалуйста, обратитесь к этому вопросу для получения дополнительной информации:

Почему C ++ поддерживает поэлементное присваивание массивов внутри структур, но не в целом?

Массивы не являются указателями. x здесь действительно относится к массиву, хотя во многих случаях он «распадается» (неявно преобразуется) до указателя на его первый элемент. Точно так же y также является именем массива, а не указателем.

Вы можете назначать массивы внутри структур:

struct data {
    int arr[10];
};

struct data x = {/* blah */};
struct data y;
y = x;

Но напрямую с массивами этого сделать нельзя. Используйте memcpy.

person Community    schedule 13.04.2009
comment
Но этот код по-прежнему не выполняет то, что он хотел, не так ли? Возможно, я ошибаюсь, но у меня сложилось впечатление, что он надеялся скопировать содержимое массива y в x. - person T.E.D.; 13.04.2009
comment
Истинный. К счастью, многие другие ответы указывают на то, что memcpy () - правильный выбор. Я добавлю ... - person ; 13.04.2009
comment
Имя массива на самом деле является адресом первого элемента этого массива. \ В приведенном здесь примере кода делается попытка присвоить чему-то, что не является l-значением: ради потомства я подумал, что отмечу, что оба эти предложения из ответа с наибольшим количеством голосов неверны. Во-первых, имя массива определенно не указатель (например, подумайте о sizeof ()), во многих случаях оно просто распадается на указатель. Во-вторых, имя массива является lvalue, а не изменяемым lvalue. - person Alexandros Gezerlis; 01.11.2011
comment
Я обдумываю этот ответ. Он получил наибольшее количество голосов и был принят, но содержал неверную информацию, и пользователь давно ушел. Надеюсь, это проясняет ситуацию. - person GManNickG; 05.10.2016

int x [sz];
int *y = x;

Это компилируется, и y будет таким же, как x.

person mikeD    schedule 23.08.2012
comment
y будет указателем, эквивалентным &x[0], из-за преобразования массива в указатель, но он не будет таким же, как x - это массив, а не указатель. - person GManNickG; 05.10.2016

В некоторых сообщениях здесь говорится, что имя массива дает адрес его первого элемента. Это не всегда правда:

#include <stdio.h>

int
main(void)
{
  int array[10];

  /*
   * Print the size of the whole array then the size of a pointer to the
   * first element.
   */
  printf("%u %u\n", (unsigned int)sizeof array, (unsigned int)sizeof &array[0]);

  /*
   * You can take the address of array, which gives you a pointer to the whole
   * array. The difference between ``pointer to array'' and ``pointer to the
   * first element of the array'' matters when you're doing pointer arithmetic.
   */
  printf("%p %p\n", (void*)(&array + 1), (void*)(array + 1));

  return 0;
}

Вывод:

40 4
0xbfbf2ca4 0xbfbf2c80
person Bastien Léonard    schedule 13.04.2009

Чтобы назначить массивы, вам нужно будет присвоить значения внутри массива.

т.е. x = y эквивалентно

for(int i = 0; i < 10 < ++i)
{
x[i] = y[i];
}
person aJ.    schedule 13.04.2009
comment
вот почему я даю эквивалент! - person aJ.; 13.04.2009
comment
создается впечатление, что x = y - верное утверждение - person Naveen; 13.04.2009
comment
На самом деле в OP уже упоминалось, что x = y не компилируется. - person aJ.; 13.04.2009
comment
Невозможность x = y для массивов - вот и весь контекст этого вопроса, Навин. - person Chuck; 13.04.2009

В попытке дополнить ответ Бланка я разработал следующую программу:

localhost:~ david$ cat test.c
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char * argv [])
{
  struct data {
    int c [2];
  } x, y;
  x.c[0] = x.c[1] = 0;
  y.c[0] = y.c[1] = 1;
  printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]);
  printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]);
  x = y;
  printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]);
  printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]);

  return 0;
}

При выполнении выводится следующее:

x.c 0x7fff5fbff870 0 0
y.c 0x7fff5fbff860 1 1
x.c 0x7fff5fbff870 1 1
y.c 0x7fff5fbff860 1 1

Дело в том, чтобы проиллюстрировать, как происходит копирование значений структур.

person David    schedule 01.06.2011

Когда "int x [10]" говорит: "Зарезервируйте место для 10 целых чисел и передайте мне указатель на местоположение". Итак, чтобы копия имела смысл, вам нужно будет работать с памятью, на которую указывает, а не с «именем ячейки памяти».

Итак, для копирования здесь вы должны использовать цикл for или memcpy ().

person amo-ej1    schedule 13.04.2009

Я использовал компиляторы C, где это прекрасно компилировалось ... и при запуске код заставлял x указывать на массив y.

Видите ли, в C имя массива - это указатель, указывающий на начало массива. Фактически, массивы и указатели по существу взаимозаменяемы. Вы можете взять любой указатель и проиндексировать его как массив.

Когда в начале 70-х разрабатывался C, он предназначался для относительно небольших программ, которые по абстракции едва ли превосходили язык ассемблера. В этой среде было чертовски удобно иметь возможность легко переключаться между индексацией массива и вычислением указателей. С другой стороны, копирование целых массивов данных было очень дорогостоящим делом, и его вряд ли можно поощрять или отвлекать от пользователя.

Да, в наше время было бы разумнее иметь сокращенное название массива для «всего массива», а не для «понтера в передней части массива». Однако C не был разработан в наше время. Если вы хотите язык, который был, попробуйте Ада. x: = y делает именно то, что вы ожидаете; он копирует содержимое одного массива в другой.

person T.E.D.    schedule 13.04.2009
comment
Дружественный случайный пинг. :) Как вы, несомненно (теперь) знаете, имя массива не является указателем. - person GManNickG; 05.10.2016