Nano Hash - криптовалюты, майнинг, программирование

typedef интерфейс функции (не указатель функции)

Если я наберу определение следующим образом:

typedef int (read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);

как определено здесь

Как называется эта техника?

Если я определяю тип таким образом, это означает, что я создаю тип read_proc_t; позже я создаю свою собственную версию read-proc-t, которая является my_read_proc, и у меня есть такая структура:

struct test {
    read_proc_t read_proc;
} 

struct test t;

Я могу сделать что-то вроде этого:

t.read_proc_t = my_read_proc;

Это правильно? Обычно, если я набираю read_proc_t в качестве указателя на функцию:

typedef int (*read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);

Мне пришлось бы присвоить адрес функции my_read_proc указателю функции, например:

(*t.read_proc_t) = &my_read_proc;

В каком случае я выбираю один?


Ответы:


1

Разница в том, что в первом случае тип read_proc_t не получает семантику неявного указателя, а во втором случае он становится типом указателя.

Разница между ними в том, что переменные первого типа не могут быть созданы в большинстве контекстов. Например, незаконно определять struct следующим образом:

struct test {
    // This causes an error in C99:
    // field ‘read_proc’ declared as a function
    read_proc_t read_proc;
};

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

struct test {
    read_proc_t *read_proc;
};

Однако read_proc_t можно использовать для объявления параметров функции:

void read_something(read_proc_t rd_proc) {
    rd_proc(...); // Invoke the function
}

Существует определенная степень взаимозаменяемости между read_proc_t и read_proc_t*: например, вы можете вызвать приведенную выше функцию следующим образом:

read_proc_t *rd = my_read_01;
read_something(rd); // <<== read_proc_t* is passed to read_proc_t

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

typedef int (*read_proc_ptr_t)(char *page, char **start, off_t off,
                      int count, int *eof, void *data);
14.04.2014

2

Это должен быть указатель. Итак, если вы наберете его следующим образом:

typedef int (read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);

Вы используете это так

read_proc_t *read_proc = my_read_proc;

И если вы наберете это так:

typedef int (*read_proc_t)(char *page, char **start, off_t off,
                           int count, int *eof, void *data);

Вы используете это так

read_proc_t read_proc = my_read_proc;
14.04.2014

3
typedef int (read_proc_t)(char *page, char **start, off_t off,
                      int count, int *eof, void *data);

Это определит read_proc_t как тип функции, вы можете определить указатель на него, например read_proc_t *read_proc, но вы не можете определить переменную этого типа. Вы struct test не работали бы.

14.04.2014

4

Во всех абсолютно всех случаях лучше использовать

typedef int (read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);

и не

typedef int (*read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);

потому что второй случай скрывает, что тип является указателем, а это плохо. Первый определяет тип, который является функцией. У вас не может быть переменных типа function в C, но указатели на функции в порядке. Итак, ваш код должен быть:

struct test {
    read_proc_t *read_proc;
}

например read_proc — указатель на функцию типа read_proc_t. Обратите внимание, что в коде четко показано, что происходит дальше. С секундным подходом вы получаете read_proc_t read_proc, который полностью скрывает аспект указателя.

14.04.2014
Новые материалы

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

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

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..