Typedef для двойного массива целых - PullRequest
1 голос
/ 10 июня 2019

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

Я пытался поиграть с разными реализациями и попытаться понять, как это работает, но результаты, которые я получил, оказались не такими, как я ожидал. Вот код, который я попытался проверить:

typedef int array[2][6];
array *arr;
arr = (array*)malloc(sizeof(array));
*arr[0][0]=2;
*arr[0][1]=4;

*arr[1][0]=3;
*arr[1][1]=5;
printf("line 1: %d %d\nline 2: %d %d\n",*arr[0][0],*arr[1][0],*arr[0][1],*arr[1][1]);
int *in = (int*) ((*arr)[0]);
printf("in = %d\n",in[1]); // results are unexpected

Код, который я на самом деле смотрю, предназначен для буфера пинг-понга и (упрощенно) выглядит следующим образом:

int buffer_count = 2; // 2 ping pong buffers
int sample_size = 15;
typedef int PingPong_t[buffer_count][sample_size];

PingPong_t *inputstream;

// logic goes here to determine pingpong_idx
int pingpong_idx = 0; // I believe this is to choose the first or second buffer

int *pcmIn = (int*)((*inputstream)[pingpong_idx]);

// do processing

Я ожидаю, что pcmIn - это целочисленный массив текущего буфера ping или pong, но у меня возникают проблемы с тем, чтобы доказать это самому себе, или я просто не уверен, что типы данных на самом деле и что они на самом деле делают.

Хороший вопрос, который у меня может возникнуть, каков тип входного потока? Правильно ли говорить, что inputtream является указателем на двойной массив целых чисел? Или inputtream - это двойной массив целочисленных указателей?

Тогда какой будет тип pcmIn?

1 Ответ

1 голос
/ 10 июня 2019

Давайте разберем его.

typedef int PingPong_t[buffer_count][sample_size];

Это сделает PingPong_t представлением двумерного массива целых чисел.Таким образом, вы можете иметь

PingPong_t p = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},{3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}};

Затем мы объявляем указатель на этот тип как

PingPong_t *inputstream;

, что означает, что inputstream является указателем на то, что PingPong_t представляет.Это не массив, не массив указателей, просто указатель.

Поскольку PingPong_t по существу означает int x[2][15], inpustream будет означать int (*y)[2][15].

Предположим, у нас было что-то вроде

inputstream = &p;

Тогда inputstream будет указывать на двумерный массив p.Настраиваемый указатель типа 2-мерный (2 x 15) int массив.

Итак, inputstream равно int (*)[2][15], а p равно int [2][15].

Теперь,Проигрывая это дальше, давайте предположим, что мы должны были увеличить inputstream.

Увеличение указателя добавит размер типа, на который он указывает.

Так, в нашем случае увеличение inpustreamдобавляет sizeof(int)*2*15 т.е. 120 (на моей машине 4 байта int).Обратите внимание, что здесь не добавляется sizeof(int), поскольку его базовый тип не int, а двумерный массив int s.

Наконец, pcmIn - это указатель int (который может бытьздесь мы будем называть это одномерным массивом), мы присваиваем как

int *pcmIn = (int*)((*inputstream)[pingpong_idx]);

, который выбирает первую строку (pingpong_idx) двумерного массива, на который указывает inputstream,и присваивает его pcmIn.

Кроме того, в приведенном выше примере вы получаете неожиданные результаты, так как присваиваете массив неправильным образом.Поскольку arr является указателем на двумерный массив, вы присваиваете значение элементу, подобному этому (*arr)[0][1]=4;, а не такому *arr[0][1]=4;.

Последнее будет означать, что arr является двумерным массивомуказатели, и вы в основном устанавливаете значение [0][1] th указатель на 4, а это не то, что вы запланировали.

arr не является двумерным массивом, поэтому arr[0][1] будет означать добавление sizeof(int)*15 до значения arr, а *arr[0][1] в основном получает / устанавливает значение по этому адресу.По сути, [0][1] th значение по-прежнему неинициализировано.

Но как тогда работают *arr[0][0]=2; и printf("in = %d\n",in[0]);?

Потому что выполнение *arr[0][0]=2; установит значение[0][0] й элемент до 2.

...