Объявление массива C и присвоение? - PullRequest
15 голосов
/ 13 апреля 2009

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

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

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

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

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

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

Ответы [ 7 ]

24 голосов
/ 13 апреля 2009

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

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

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

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

struct data {
    int arr[10];
};

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

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

4 голосов
/ 23 августа 2012
int x [sz];
int *y = x;

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

2 голосов
/ 13 апреля 2009

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

#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
1 голос
/ 01 июня 2011

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

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

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

1 голос
/ 13 апреля 2009

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

т. х = у эквивалентно

for(int i = 0; i < 10 < ++i)
{
x[i] = y[i];
}
0 голосов
/ 13 апреля 2009

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

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

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

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

0 голосов
/ 13 апреля 2009

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

Так что для копирования вы бы использовали цикл for или memcpy ().

...