Странная конструкция C встречается в академической статье - PullRequest
3 голосов
/ 07 августа 2010

Код гласит:

void (* log_msg)(char *msg)
    =printf;

void change_and_log(int *buffer, int offset, int value){
    buffer[offset] = value;
    log_msg("changed");
}

Меня больше всего волнует первая часть:

Во-первых, что означает подпись void (* log_msg)(char *msg)?Этот код просто отображает функцию log_msg на printf?В таком случае, почему имя функции (* log_msg), а не просто log_msg?

Ответы [ 4 ]

6 голосов
/ 07 августа 2010

void (* log_msg)(char *msg) фактически указатель на функцию.Вы можете просмотреть это как

typedef void (*LoggerFunctionPointer)(char* msg);

LoggerFunctionPointer log_msg = printf;

Да, оно отображает log_msg на printf, но нет, log_msg не функция, а указатель, указывающий на функцию printf.

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

void no_log_msg(char* msg) {}
...
if (enable_debug) {
  log_msg = printf;
} else {
  log_msg = no_log_msg;
}

, тогда, без изменения другого исходного кода, вся регистрация может быть заблокирована.неверно, поскольку подпись printf равна int printf(const char*, ...). Чтобы избежать неявного приведения, log_msg следует объявить как

int (*log_msg)(const char*, ...) = printf;

)

2 голосов
/ 07 августа 2010

log_msg - это указатель на функцию , в частности «указатель на функцию, принимающую char * и возвращающую void». В этом случае он просто используется как псевдоним для printf (но может указывать на любую функцию с такими же аргументами и типом возвращаемого значения).

Синтаксис для указателей на функции в C поначалу может быть довольно пугающим.

2 голосов
/ 07 августа 2010

Это указатель на функцию .

Тип указателя на функцию R (*)(Args...), где R и Args... заменены типом возвращаемого значения и аргументами, если таковые имеются,Он читается как «указатель на функцию, которая принимает аргументы Args... и возвращает R

Ваш код будет читаться проще как:

// print_function is a type that is a function pointer
typedef void (*print_function)(char *msg); 

// log_msg is a variable of the type print_function: it points to a function
print_function log_msg = printf; // point to printf

А позже это простовызов этой функции через указатель на функцию.

2 голосов
/ 07 августа 2010

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

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