Ответ 1
Как выделяется массив выделенных структур
В вашем случае массив MyData[2]
выглядит следующим образом:
| count | name | average | count | name | average |
^ -- your ptr points here
Это одно непрерывное пространство с размером 3 * sizeof (struct MyData)
.
Всякий раз, когда вы выполняете операцию ptr++
, указатель переместится к следующей структуре массива, что означает, что он учитывает размер одного struct MyData
.
| count | name | average | count | name | average |
^ -- after ptr++ your ptr points here
После другого ptr++
ваш указатель укажет на память сразу после вашего массива.
| count | name | average | count | name | average |
^ -- another ptr++ and your ptr points here
Когда вы разыскиваете свой указатель ptr
, вы получаете доступ к памяти, которая еще не используется или даже не выделяется. Это поведение undefined и из-за этого сбой приложения.
Как выполнить итерацию?
Есть несколько способов сделать это. Обратите внимание, что не все способы применимы во всех случаях.
Простой для
Очень часто мы просто знаем размер массива. Затем мы можем просто использовать обычный цикл for
для итерации содержимого.
int len = 2;
struct MyData data[len] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
for (int i=0; i<2; i++, ptr++ ) {
// do your thing with the ptr
// and note that ptr gets increased inside for
}
Использование sizeof для определения длины массива
struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
struct MyData* endPtr = data + sizeof(data)/sizeof(data[0]);
while ( ptr < endPtr ){
// do your thing with the ptr
ptr++;
}
sizeof(data)/sizeof(data[0])
вычисляет количество элементов: получает общий размер массива и делит его на размер одного элемента.
Этот метод имеет свои недостатки. Он не может использоваться, когда массив объявлен как указатель! Например, когда мы передаем массив как параметр функции, он обычно преобразуется в указатель, и мы не можем определить размер массива.