инициализация структур и передача по ссылке - PullRequest
0 голосов
/ 18 октября 2018

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

typedef struct uint8array {
 uint8 len;
 uint8 data[];
} uint8array;

int compare_uint8array(uint8array* arr1, uint8array* arr2) {
  printf("%i %i\n data: %i, %i\n", arr1->len, arr2->len, arr1->data[0], arr2->data[0]);
  if (arr1->len != arr2->len) return 1;
  return 0;
  }

int compuint8ArrayTest() {
 printf("--compuint8ArrayTest--\n");
 uint8array arr1;
 arr1.len = 2;
 arr1.data[0] = 3;
 arr1.data[1] = 5;    

 uint8array arr2;
 arr2.len = 4;
 arr2.data[0] = 3;
 arr2.data[1] = 5;    
 arr2.data[2] = 7;    
 arr2.data[3] = 1;    

 assert(compare_uint8array(&arr1, &arr2) != 0);
}

Теперь вывод этой программы:

 --compuint8ArrayTest--
 3 4
 data: 5, 3

Почему значения не те, к которым я их инициализировал?Что мне здесь не хватает?

1 Ответ

0 голосов
/ 18 октября 2018

В вашем случае uint8 data[]; является гибким элементом массива .Вам нужно выделить память для data, прежде чем вы сможете получить к ней доступ.

В вашем коде вы пытаетесь получить доступ к неверному расположению памяти, вызывая неопределенное поведение .

Цитирование C11, глава §6.7.2.1 ( выделение шахты )

В качестве особого случая последний элемент структуры с несколькими именованными элементами может иметьтип неполного массива;это называется членом гибкого массива.В большинстве случаев член гибкого массива игнорируется.В частности, размер структуры такой, как если бы элемент гибкого массива был опущен, за исключением того, что он может иметь больше завершающего дополнения, чем предполагалось бы в случае пропуска.Но когда а.(или ->) оператор имеет левый операнд, который является (указателем) на структуру с элементом гибкого массива, а правый операнд называет этот член, он ведет себя так, как если бы этот элемент был заменен самым длинным массивом (с тем же типом элемента) это не сделает структуру больше, чем объект, к которому осуществляется доступ;смещение массива должно оставаться смещением элемента гибкого массива, даже если оно будет отличаться от смещения массива замены. Если в этом массиве нет элементов, он ведет себя так, как если бы у него был один элемент, но поведение не определено, если предпринята какая-либо попытка получить доступ к этому элементу или сгенерировать указатель один за ним.

Правильный пример использования также можно найти в главе §6.7.2.1

ПРИМЕР 2 После объявления:

struct s { int n; double d[]; };

структура struct s имеет гибкийчлен массива d.Типичный способ использовать это:

int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));

и, предполагая, что вызов malloc успешен, объект, на который указывает p, ведет себя в большинстве случаев так, как если бы был объявлен pкак:

struct { int n; double d[m]; } *p;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...