Назначить указатель на массив 2D void в структуре на C99

#c #arrays #pointers #struct

#c #массивы #указатели #структура

Вопрос:

У меня есть 2d буфер, который я хотел бы передать потоку вместе с другими значениями, поэтому мне нужно переместить его в структуру. Когда я пытаюсь это сделать, я не могу снова получить доступ к значениям в моей структуре, и мне нужна некоторая помощь.

Вот мой буфер:

 void* mybuff[8][16384];
  

Я хотел бы сохранить указатель на этот 2D-массив в структуре, подобной этой:

 typedef struct  {
  int i;
  void *mybuff;
} arg_struct_t;
  

Однако, если я попытаюсь получить доступ к значениям:

     arg_struct_t *args = malloc(sizeof(arg_struct_t));
    args->i = index;
    args->mybuff = mybuff;

    fprintf(stderr, "%pn", args->mybuff[0][0]);
  

Я получаю сообщение об ошибке:

 main.c:104:47: warning: dereferencing ‘void *’ pointer [enabled by default]
           fprintf(stderr, "%pn", args->mybuff[0][0]);
                                               ^
main.c:104:50: error: subscripted value is neither array nor pointer nor vector
           fprintf(stderr, "%pn", args->mybuff[0][0]);
                                                  ^
  

Я думаю, мне нужно рассказать C99 больше о форме данных, которые я хочу поместить в свою структуру, но я не совсем понимаю, как это правильно сделать. Я ценю любую помощь или идеи здесь.

Комментарии:

1. При сохранении mybuff в структуре теряется вся информация о типе. Поэтому вам нужно восстановить эту информацию, присвоив args->mybuff указателю правильный тип, например void * (*myptr)[16384] = args->mybuff .

2. что касается: void* mybuff[8][16384]; Это объявление буфера из 64 тысяч указателей. Это то, чего вы действительно хотели. Примечание: в 32-разрядной архитектуре это приводит к 64 кб * 4 байтам в стеке. Не очень хорошая идея размещать так много данных в стеке

Ответ №1:

Компилятор не знает, какой адрес в памяти он должен здесь вычислить:

 args->mybuff[0][0]
  

потому что args->mybuff это просто указатель на void. Для обработки такого выражения компилятору требуется информация о 1) размере элементов массива и 2) хотя бы одном из измерений массива.
Следующий код более корректен:

 typedef void* TBuff[8][16834];
TBuff mybuff;

typedef struct  {
  int i;
  TBuff * mybuff;
} arg_struct_t;

arg_struct_t *args = malloc(sizeof(arg_struct_t));
args->i = index;
args->mybuff = amp;mybuff;
fprintf(stderr, "%pn", (*args->mybuff)[0][0]);
  

Комментарии:

1. @M.M, почему косвенное обращение *mybuff ? Я только сейчас заметил и исправил, что использовал переменную mybuff вместо поля args->mybuff .

2. очень плохая практика программирования — скрывать указатель в typedef

Ответ №2:

Рискуя завести вас еще дальше:

 typedef struct  {
  int i;
  void* mybuff[8][16384];
} arg_struct_t;
  

Но общая природа void * — это общая типизация, которая противоречит многомерным массивам. Этот код выглядит странно, как только появляется этот тип, и, вероятно, что-то еще не так.

Ответ №3:

Вот как сохранить адрес mybuff и как использовать этот указатель позже для доступа к значениям.

 int main()
{
    // Starting array    
    int* mybuff[8][16384];

    // Save the address of mybuff into 'p'. 'p' is a pointer to (int*)'s
    int** p = amp;mybuff[0][0];

    // Access the location of row=3, col=4 using 'p'
    int r = 3;
    int c = 4;
    *(p   (r*16384   c)) = (int*) 123; // 123 is the value to assign

    return 0;
}
  

Таким образом, вам также нужно будет передать размеры строк и столбцов (8 и 16384) в вашей структуре, чтобы разыменовать значения. Для краткости я не стал проверять границы в примере, но вы должны сделать это в реальном коде.