C жестким кодированием массива typedef struct - PullRequest
3 голосов
/ 21 апреля 2009

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

У меня есть библиотека с определенной структурой typedef. в основном:

typedef struct {int x; int y;} coords;

Что я действительно хотел сделать, так это объявить в своем заголовке массив переменных:

coords MyCoords[];

(недавно я переключил его на coords *MyCoords;, а затем запустил MyCoords = new coords[4];)

и затем в моем init я хотел жестко закодировать некоторые значения в нем.

MyCoords[] = {{0, 0}, {2, 2} etc. 

Сегодня я просто должен думать, потому что это не позволяет мне делать какие-либо вещи, просто вставляя что-то простое, как MyCoords[0] = {0, 0}

извините за синтаксис, приведенный выше. Спасибо за любую помощь. Меня даже не волнует жесткое кодирование всех значений одновременно. Теперь я в порядке, только с работой MyCoords[0] = {0, 0}. Я мог бы сделать MyCoords[0].x = 0; MyCoords[0].y = 0, но тогда я бы никогда не понял, что я делаю неправильно. Большое спасибо всем ..

Ответы [ 4 ]

9 голосов
/ 21 апреля 2009

Вы можете инициализировать массив только в том месте, где вы его объявили. Форма, которая будет работать:

coords MyCoords[] = {{0, 0}, {2, 2}};

Если вам нужно объявить MyCoords в заголовке, чтобы многие модули могли получить к нему доступ, я думаю, что будет работать следующее:

extern coords MyCoords[];
5 голосов
/ 21 апреля 2009

Ну, то, что вы создали, не является массивом переменных. Это массив, размер которого неизвестен. Этот массив имеет неполный тип и поэтому не может быть определен в C ++. Что вы можете сделать, это сделать это просто объявлением, поставив перед ним extern.

extern coords MyCoords[];

Затем в файле .cpp, который его инициализирует, вы можете затем создать (определить) этот массив - будьте осторожны, вы должны делать это в области имен, вне какой-либо функции, конечно:

coords MyCoords[] = {{1, 2}, {3, 4}, ... };

Если вам нужен массив, размер которого еще не известен во время компиляции, а скорее во время выполнения, вы должны использовать std::vector:

std::vector< coords > MyCoords;

Затем, если вы заполните его, выполните

MyCoords.push_back( coords(1, 2) );
MyCoords.push_back( coords(3, 4) );
....

Или создайте локальный массив и затем инициализируйте вектор, используя копию элементов этого массива:

coords c[] = ....;
MyCoords.insert(MyCoords.end(), c, c + sizeof c / sizeof *c);

Ну, в C это немного отличается от C ++. Вы можете определить массив, размер которого неизвестен. Что происходит, так это то, что это «предварительное» определение. Если в конце файла (точнее, его единицы перевода, которой является этот файл, и всех файлов, которые он включает - то есть все, что компилятор переводит вместе), нет последующего его определения, включающего размер, то размер принимается за 1. Однако в C ++ нет предварительных определений, и определение, которое не включает размер и не содержит инициализатор, который может сказать, что размер является недопустимой программой C ++.

По причине того, что ваш код работает нормально, вы делаете

MyCoords[0] = {0, 0}

Что компилятор будет читать как:

-> Set LHS to RHS
-> -> LHS is a variable of type `coords`. Fine
-> -> RHS is... hmm, `{0, 0}`. What the heck is it??

Видите ли, компилятор понятия не имеет, что должна означать правая часть. По этой причине C99 (версия C 1999 года) ввел так называемые составные литералы. Позволяет написать

MyCoords[0] = (coords){0, 0};

И он на самом деле будет делать то, что вы хотите, - создавая правое значение типа coord и присваивая его левой стороне. Но вы должны просто, уже по причине совместимости (многие компиляторы C не являются разумно совместимыми с C99 - и ни C ++, ни C89 не поддерживают составные литералы), используйте один из предыдущих способов, которые я вам показал.

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

Я не уверен, является ли это также проблемой в вашем реальном коде, но:

typedef struct coords {int x, int y};

не является полным объявлением typedef в C, поскольку оно не дает имя для type , только для struct (теги struct не находятся в том же пространстве имен, что и имена типов в стандартном C). Чтобы сделать объявление typedef правильным, вы должны указать имя для всего типа struct coords {int x, int y}, как если бы вы объявляли переменную этого типа, например:

typedef struct coords {int x, int y} coords;
0 голосов
/ 21 апреля 2009

Должно быть:

typedef struct coords {int x, int y} coords;
coords MyCoords[] = {{0, 0}, {2, 2}, {3, 4}};
...