Объявление и назначение массива 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 делает именно то, что вы ожидаете; он копирует одно содержимое массива в другое.