C существующий указатель на массив фиксированного размера - PullRequest
1 голос
/ 22 февраля 2012

Предположим, что в любой функции C указатель уже объявлен, но ему еще не присвоено значение. Мы будем int для наших примеров.

int *ptr;  

Цель функции - не назначать ptr динамической памяти в куче, поэтому нет вызова malloc. Вместо этого мы хотим, чтобы он указывал на массив фиксированного размера n. Я знаю, что мог бы сделать это так:

int arr[n];
ptr = arr;

Однако код может стать очень запутанным и трудным для чтения, если нам нужно будет делать это много раз в функции, т. Е. Структура многих полей указателей должна указывать на массив фиксированной длины. Есть ли лучший способ сделать это в одной строке? Я думал о чем-то похожем на ниже, но это выглядит слишком двусмысленным и не компилируемым:

int *ptr;
// Many other things happen in between...
ptr[n];

*** **** EDIT 1014 *
Здесь приведенная ниже дополнительная информация может помочь направить некоторые ответы (не говоря о том, что текущие ответы не подходят). В моем случае использования указатели объявляются в структуре, а в функции я присваиваю указатели массиву. Я хочу знать, есть ли более простой способ сделать это, чем в приведенном ниже коде (все указатели указывают на массив фиксированной длины):

struct foo {
    int* a;
    short* b;
    char* c;
    ...
};

void func(void) {
    struct foo f;
    int n = ...;
    int tempArr1[n];
    f.a = tempArr1;
    short tempArr2[n];
    f.b = tempArr2;
    char tempArr3[n];
    f.c = tempArr3;
    ...
}

Ответы [ 4 ]

1 голос
/ 22 февраля 2012

Вы не можете объявить массив и назначить его существующему указателю в одном объявлении. Однако вы можете назначить указатель массива для вновь объявленного указателя , например:

int arr[n], *ptr = arr;

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

#define DECL_ASSIGN_INT_ARRAY(name,size,pointer) int name[(size)]; pointer = name;

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

РЕДАКТИРОВАТЬ (в ответ на редактирование вопроса)

Другой вариант - создать неиспользуемую переменную-указатель в объявлении и назначить указатель в инициализаторе, например:

void func(void) {
    struct foo f;
    int n = ...;
    int tempArr1[n], *tempPtr1 = f.a = tempArr1;
    short tempArr2[n], *tempPtr2 = f.b = tempArr2;
    char tempArr3[n], *tempPtr3 = f.c = tempArr3;
    ...
}
0 голосов
/ 22 февраля 2012

Разница между ptr и arr в вашем примере заключается в том, что вы можете изменить значение ptr.Так что я думаю, что вы хотите переместить ptr по массиву.

Так как насчет этого:

int arr[n], id=0;

И вы меняете значение id и используете arr+id в качестве ptr.

0 голосов
/ 22 февраля 2012

Я думаю, что способ сделать это - использовать макрос.Что-то вроде (не проверено)

 #define autoptr(name,size) int Arrayname[size]; name = Arrayname;

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

0 голосов
/ 22 февраля 2012

Это похоже на очевидный случай, когда вам нужен какой-то рефакторинг. Возьмите аналогичные операторы, извлеките их в новую функцию (передав ссылку на структуру и данные, на которые вы хотите указать поля структуры) и дайте этой новой функции осмысленное имя.

Это, вероятно, более легко обслуживаемо и читабельно, чем какой-нибудь причудливый арифметический указатель, о котором вы забудете через несколько недель или месяцев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...