Как каждый объявляет массив указателей постоянной функции в C?

Более безопасная и быстрая (удвоенная емкость) версия:

char *readline(char *prompt) {
  size_t size = 80;
  char *str = malloc(sizeof(char) * size);
  int c;
  size_t len = 0;
  printf("%s", prompt);
  while (EOF != (c = getchar()) && c != '\r' && c != '\n') {
    str[len++] = c;
    if(len == size) str = realloc(str, sizeof(char) * (size *= 2));
  }
  str[len++]='\0';
  return realloc(str, sizeof(char) * len);
}
22
задан Judge Maygarden 3 December 2008 в 15:50
поделиться

5 ответов

Существует техника, чтобы помнить, как создать такой тип. Сначала попытайтесь считать указатели, начинающие с их имени и читать справа налево.

, Как объявить тот материал без справки?

Массивы

T t[5];

массив 5 T. Для создания T функциональным типом Вы пишете тип возврата налево и параметры направо:

void t[5](void);

был бы быть массив 5 функций, возвращаясь пусто и не беря параметров . Но функционирует, самостоятельно не может быть наполнен в массивах! Они не объекты. Только указатели на них могут.

Что относительно [1 141]

void * t[5](void);

Это все еще неправильно, поскольку это просто изменило бы тип возврата, чтобы быть указателем на пустоту. Необходимо использовать круглые скобки:

void (*t[5])(void);

и это будет на самом деле работать. т является массивом 5 указателей на функции, возвращаясь пусто и не беря параметров .

Здорово! Что относительно массива указателей на гобелены? Это очень похоже. Тип элемента появляется слева, и размер справа. Снова, круглые скобки необходимы, потому что иначе массив стал бы многомерным массивом целочисленных указателей:

int (*t[5])[3];

Вот именно! массив 5 указателей на массивы 3 интервалов .

Что относительно функций?

то, Что мы только что изучили, верно о функциях также. Давайте объявим функцию, берущую интервал, который возвращает указатель на другую функцию, берущую параметр и возвращающуюся пусто:

void (*f(int))(void);

нам нужны круглые скобки снова поскольку он та же причина как выше. Мы могли теперь назвать его и вызвать возвращенную функцию, указал снова.

f(10)();

Возврат указателя на функцию, возвращая другой указатель на функцию

Что относительно этого?

f(10)(true)(3.4);

? Другими словами, как функционировал бы, беря интервал, возвращая указатель на функцию, берущую bool возврат указателя на функцию, берущую дважды, и возвращающийся пусто будет похож? Ответ - то, что Вы просто вкладываете их:

void (*(*f(int))(bool))(double);

Вы могли сделать так бесконечные времена. Действительно, можно также возвратить указатель на массив точно так же, как Вы можете указатель на функцию:

int (*(*f(int))(bool))[3];

Это функция берет интервал, возвращая указатель на функцию, берущую bool возврат указателя на массив 3 интервалов

, Что это имеет отношение к константе?

Теперь, когда вышеупомянутое объяснило, как создать типы complexer от фундаментальных типов, можно поместить const в места, где Вы теперь знаете, где они принадлежат. Просто рассмотрите:

T c * c * c ... * c name;

Эти T основной тип, на который мы заканчиваем тем, что указали в конце. Эти c обозначает или константу или нет, константа, Например

int const * const * name;

объявит, что имя имеет указатель типа на постоянный указатель на постоянный интервал . Можно измениться name, но Вы не можете измениться *name, который имел бы тип

int const * const

и никакой **name, который будет иметь тип

int const

, давайте применим это к указателю функции вышеупомянутых:

void (* const t[5])(void);

Это на самом деле объявило бы, что массив содержит постоянные указатели. Таким образом, после создания (и инициализация) массив, эти указатели являются константой, потому что эти const появился после звезды. Обратите внимание, что мы не можем поместить const перед звездой в этом случае, с тех пор нет никаких указателей на постоянные функции . Функции просто не могут быть константой, поскольку это не имело бы смысла. Таким образом, следующее не допустимо:

void (const * t[5])(void);

Заключение

C++ и способ C объявить функции и массивы на самом деле на самом деле немного сбивают с толку. Необходимо получить голову вокруг этого сначала, но если Вы понимаете его, можно записать очень компактные объявления функции с помощью него.

57
ответ дан Johannes Schaub - litb 29 November 2019 в 03:24
поделиться

cdecl говорит:

cdecl> explain void (* const foo[])(void)
declare foo as array of const pointer to function (void) returning void

он, в чем Вы нуждаетесь?

15
ответ дан qrdl 29 November 2019 в 03:24
поделиться

В таких ситуациях сделайте typedef для именования функциональной подписи, которая делает его намного более простым:

typedef void MESSAGE_HANDLER(void);

с тем на месте, это должно быть справедливо:

MESSAGE_HANDLER * const handlers[] = { function1, function2 };

Для получения фактического содержания константы массива.

РЕДАКТИРОВАНИЕ : Удаленная часть указателя от эти typedef, это действительно лучше (живите и учитесь).

15
ответ дан unwind 29 November 2019 в 03:24
поделиться

С VisualStudio 2008 я добираюсь:

void (* const MESSAGE_HANDLERS[])(void) = {
   NULL,
   NULL
};

int main ()
{
    /* Gives error 
        '=' : left operand must be l-value
    */
    MESSAGE_HANDLERS = NULL;

    /* Gives error 
        l-value specifies const object
    */
    MESSAGE_HANDLERS[0] = NULL;
}
1
ответ дан David Norman 29 November 2019 в 03:24
поделиться

Я не уверен, будет ли это работать в 'C'. это действительно работает в 'C++':

  • Первый определяют MESSAGE_HANDLERS как тип:

    typedef void (*MESSAGE_HANDLER)();

  • Затем используйте определение типа для объявления массива константа:

    MESSAGE_HANDLER const handlers[] = {function1, function2};

прием находится в эти typedef, если можно сделать то же семантически в 'C', это должно работать также.

1
ответ дан Delimitry 29 November 2019 в 03:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: