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

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

Предположим, у меня есть два массива:

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

Почему х = у не компилируется? Если они оба являются одинаковыми "сигнатурами", то не следует ли их назначать туда и обратно?

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

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

Ответы

Ответ 1

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

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

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

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

struct data {
    int arr[10];
};

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

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

Ответ 2

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

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

Ответ 3

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

#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

Ответ 4

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

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

for(int i = 0; i < 10 < ++i)
{
x[i] = y[i];
}

Ответ 5

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

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

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

Ответ 6

Говоря "int x [10]" говорит ", зарезервируйте место для 10 целых чисел и передайте мне указатель на местоположение". Поэтому для того, чтобы копия имела смысл, вам нужно будет использовать указанную память, а не "имя ячейки памяти".

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

Ответ 7

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

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

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

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