Инициализация массивов typedef в структурах - PullRequest
0 голосов
/ 21 декабря 2018

Я делаю структуру камеры.В структуре используется vec3, которая определяется с помощью typedef float vec3[3].

Для инициализации vec3 Я делаю vec3 vector = {0.,0.,0.};

Моя Cameras структура выглядит следующим образом:

typedef struct Cameras {
    vec3 eye;
    vec3 target
} Camera;

но когда я делаю:

Camera cam;
cam.eye = { .5, 1., 0. };

, он падает, и компилятор говорит мне: expression must be modifiable.

Я думал, что это ошибка с указателем, но нет, изамена vec3 eye на vec3 * eye и cam->eye = {.5,1.,0.} ничего не меняет.

Я создаю структуру неправильно или это действительно распространенная проблема C, и я просто слепой?

здесьМоя цель - не только инициализировать массив, но также получить доступ к данным и модифицировать / передать их в функцию после создания.

Ответы [ 3 ]

0 голосов
/ 21 декабря 2018

Я лично предпочитаю более «описательную» инициализацию - мне нравится указывать членов - код легче читать людям.

typedef float vec3[3];

typedef struct Cameras {
    vec3 eye;
    vec3 target;
} Camera;

Camera c = 
{
  .eye = {1.0, 2.0, 3.0},   
  .target = {4.0, 5.0, 6.0},   
};

Camera c1 = 
{
  .target = {4.0, 5.0, 6.0},   
};

Camera c2 = 
{
  .eye = {1.0, 2.0, 3.0},   
};
0 голосов
/ 21 декабря 2018

Ошибка, которую вы получаете, очевидна, тип vec3 равен float [3] - тип массива, и вы определенно не можете «назначить» типам массива.

Вы можете использовать инициализацию, как указано iBug в другом ответе.Тем не менее, с небольшим трюком вы также сможете использовать это задание.Для этого потребуется использовать указатель и составной литерал .

. Вам нужно изменить typedef на vec3

 typedef float* vec3;

, чтобы сделать егоa float * и затем вы можете использовать составной литерал для присвоения значений, например

cam.eye = (float [3]){ .5, 1., 0. };
cam.target = (float [3]){ .45, 2.5, 0.9 }; // just some other values.

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

PS - Составные литералы можно изменять , поэтому вы не потеряете какие-либо операционные возможности.

PPS

Цитирование C11, глава §6.5.2.5 / P12

"/tmp/fileXXXXXX" 
 (char []){"/tmp/fileXXXXXX"} 
 (const char []){"/tmp/fileXXXXXX"} 

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

0 голосов
/ 21 декабря 2018

Это потому, что после определения строки cam последующие «назначения» больше не являются инициализациями .

К инициализации экземпляра, вы должны поместить"присваивание" в том же месте, где оно определено:

Camera cam = { {.5, 1., 0.} };

или указание члена:

Camera cam = { .eye = {.5, 1., 0.} };

Обратите внимание, что это также автоматически инициализируется нулями cam.target, поскольку никакие начальные значения не являютсяуказано для него.

...