Назначить несколько значений массиву в C
Есть ли способ сделать это в сжатой форме?
GLfloat coordinates[8];
...
coordinates[0] = 1.0f;
coordinates[1] = 0.0f;
coordinates[2] = 1.0f;
coordinates[3] = 1.0f;
coordinates[4] = 0.0f;
coordinates[5] = 1.0f;
coordinates[6] = 0.0f;
coordinates[7] = 0.0f;
return coordinates;
Что-то вроде coordinates = {1.0f, ...};
?
Ответы
Ответ 1
Если вы действительно назначаете значения (в отличие от инициализации), вы можете сделать это следующим образом:
GLfloat coordinates[8];
static const GLfloat coordinates_defaults[8] = {1.0f, 0.0f, 1.0f ....};
...
memcpy(coordinates, coordinates_defaults, sizeof(coordinates_defaults));
return coordinates;
Ответ 2
Есть трюк, чтобы обернуть массив в структуру (которая может быть инициализирована после объявления).
т.
struct foo {
GLfloat arr[10];
};
...
struct foo foo;
foo = (struct foo) { .arr = {1.0, ... } };
Ответ 3
Путь старой школы:
GLfloat coordinates[8];
...
GLfloat *p = coordinates;
*p++ = 1.0f; *p++ = 0.0f; *p++ = 1.0f; *p++ = 1.0f;
*p++ = 0.0f; *p++ = 1.0f; *p++ = 0.0f; *p++ = 0.0f;
return coordinates;
Ответ 4
Точно, вы почти получили его:
GLfloat coordinates[8] = {1.0f, ..., 0.0f};
Ответ 5
Вы можете использовать:
GLfloat coordinates[8] = {1.0f, ..., 0.0f};
но это инициализация времени компиляции - вы не можете использовать этот метод в текущем стандарте для повторной инициализации (хотя я думаю, что есть способы сделать это в предстоящем стандарте, что может не сразу помочь вам).
Другими двумя способами, чтобы spring было умыть содержимое, если они исправлены:
GLfloat base_coordinates[8] = {1.0f, ..., 0.0f};
GLfloat coordinates[8];
:
memcpy (coordinates, base_coordinates, sizeof (coordinates));
или предоставить функцию, которая похожа на ваш код инициализации:
void setCoords (float *p0, float p1, ..., float p8) {
p0[0] = p1; p0[1] = p2; p0[2] = p3; p0[3] = p4;
p0[4] = p5; p0[5] = p6; p0[6] = p7; p0[7] = p8;
}
:
setCoords (coordinates, 1.0f, ..., 0.0f);
имея в виду, что эти эллипсы (...
) являются заполнителями, а не буквально вставляются в код.
Ответ 6
Если вы часто выполняете эти же задания в своей программе и хотите использовать ярлык, самым простым решением может быть просто добавить функцию
static inline void set_coordinates(
GLfloat coordinates[static 8],
GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3,
GLfloat c4, GLfloat c5, GLfloat c6, GLfloat c7)
{
coordinates[0] = c0;
coordinates[1] = c1;
coordinates[2] = c2;
coordinates[3] = c3;
coordinates[4] = c4;
coordinates[5] = c5;
coordinates[6] = c6;
coordinates[7] = c7;
}
а потом просто позвонить
GLfloat coordinates[8];
// ...
set_coordinates(coordinates, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f);
Ответ 7
С таким кодом:
const int node_ct = 8;
const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };
И в configure.ac
AC_PROG_CC_C99
Компилятор на моей коробке разработчика был счастлив. Компилятор на сервере жаловался на:
error: variable-sized object may not be initialized
const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };
а также
warning: excess elements in array initializer
const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };
для каждого элемента
Это не жалуется, например, на:
int expected[] = { 1, 2, 3, 4, 5 };
Однако я решил, что мне нравится проверка размера.
Вместо того, чтобы сражаться, я пошел с инициализатором varargs:
#include <stdarg.h>
void int_array_init(int *a, const int ct, ...) {
va_list args;
va_start(args, ct);
for(int i = 0; i < ct; ++i) {
a[i] = va_arg(args, int);
}
va_end(args);
}
называется как,
const int node_ct = 8;
int expected[node_ct];
int_array_init(expected, node_ct, 1, 3, 4, 2, 5, 6, 7, 8);
Таким образом, поддержка varargs является более надежной, чем поддержка инициализатора массива.
Кто-то может сделать что-то подобное в макросе.
Найдите PR с примером кода на https://github.com/wbreeze/davenport/pull/15/files
Что касается fooobar.com/questions/214061/... от @paxdiablo, мне понравилось; но чувствовал себя неуверенно из-за того, что количество перемещений указателя инициализации синхронизировалось с количеством элементов, выделенных массиву. В худшем случае указатель инициализации выходит за пределы выделенной длины. Таким образом, разница в PR содержит:
int expected[node_ct];
- int *p = expected;
- *p++ = 1; *p++ = 2; *p++ = 3; *p++ = 4;
+ int_array_init(expected, node_ct, 1, 2, 3, 4);
Метод int_array_init
безопасно назначит мусор, если число аргументов меньше, чем node_ct. Назначение мусора должно быть легче поймать и отладить.
Ответ 8
typedef struct{
char array[4];
}my_array;
my_array array = { .array = {1,1,1,1} }; // initialisation
void assign(my_array a)
{
array.array[0] = a.array[0];
array.array[1] = a.array[1];
array.array[2] = a.array[2];
array.array[3] = a.array[3];
}
char num = 5;
char ber = 6;
int main(void)
{
printf("%d\n", array.array[0]);
// ...
// this works even after initialisation
assign((my_array){ .array = {num,ber,num,ber} });
printf("%d\n", array.array[0]);
// ....
return 0;
}