typedef int (fc_name) (void);
Здесь fc_name
- любой действительный символ C.
Насколько это отличается от указателя функции typedef
?
typedef int (fc_name) (void);
Здесь fc_name
- любой действительный символ C.
Насколько это отличается от указателя функции typedef
?
Это a typedef
для типа функции. Цель состоит в том, чтобы использовать его для указателей на функции, но в этом случае синтаксис для его использования будет:
int bar(void);
fc_name* foo = bar; /* Note the * */
Обновление:
Как упоминалось в комментариях к ответ Джонатана Леффлера, typedef
может использоваться для объявления функций. Одно использование может заключаться в объявлении набора функций обратного вызова:
typedef int (callback)(int, void*);
callback onFoo;
callback onBar;
callback onBaz;
callback onQux;
Первые круглые скобки являются излишними - это эквивалентно:
typedef int fc_name(void);
Я не думаю, что это ничего полезного, хотя я не могу заставить GCC жаловаться на это сам.
Это означает, что fc_name
является псевдонимом для типа функции, который не принимает аргументов и возвращает int
. Это не всегда полезно, хотя вы можете объявить, например, функцию rand()
, используя:
fc_name rand;
Вы не можете использовать typedef
в определении функции.
Указатель на функцию typedef будет читать:
typedef int (*fc_name)(void);
Этот код показывает, что typedefs без звездочки не являются указателями на функции (адресация теперь альтернативного ответа):
static int function(void)
{
return 0;
}
typedef int fc_name1 (void);
typedef int (fc_name2)(void);
typedef int (*fc_name3)(void);
fc_name1 x = function;
fc_name2 y = function;
fc_name3 z = function;
При компиляции 'gcc' говорит:
gcc -Wextra -Wall -pedantic -c -O x.c
x.c:10:1: error: function ‘x’ is initialized like a variable
x.c:11:1: error: function ‘y’ is initialized like a variable
И этот код демонстрирует, что вы действительно можете использовать fc_name *var = funcname;
, как предложено jamesdlin:
static int function(void)
{
return 0;
}
typedef int fc_name1 (void);
typedef int (fc_name2)(void);
typedef int (*fc_name3)(void);
fc_name1 x_0 = function;
fc_name1 *x_1 = function;
fc_name2 y_0 = function; // Damn Bessel functions - and no <math.h>
fc_name2 *y_1 = function; // Damn Bessel functions - and no <math.h>
fc_name3 z = function;
Используя y0, y1 генерирует предупреждения GCC:
x.c:12:11: warning: conflicting types for built-in function ‘y0’
x.c:13:11: warning: built-in function ‘y1’ declared as non-function
И, основываясь на комментарии от schot:
static int function(void)
{
return 0;
}
typedef int fc_name1 (void);
typedef int (fc_name2)(void);
typedef int (*fc_name3)(void);
fc_name1 x_0 = function; // Error
fc_name1 *x_1 = function; // x_1 is a pointer to function
fc_name1 x_2; // Declare int x_2(void);
fc_name1 *x_3 = x_2; // Declare x_3 initialized with x_2
fc_name2 y_0 = function; // Damn Bessel functions - and no <math.h>
fc_name2 *y_1 = function; // Damn Bessel functions - and no <math.h>
fc_name1 y_2; // Declare int y_2(void);
fc_name1 *y_3 = x_2; // Declare y_3 initialized with y_2
fc_name3 z = function;
Интересно - темные углы C действительно мутные.
Интересно! Объявление typedef является объявлением с типедефом в качестве класса хранения.
typedef int fc_name1 (void);
// this defines a function type called fc_name1
// which takes no parameter and returns int
позже вы можете определить функцию, например следующую,
fc_name1 myFunc;
// this is equivalent to the next line
// int myFunc(void);
Вы должны понять это из стандарта c/С++!
Я никогда раньше не видел, чтобы это было сделано с именем typedef, но круглые скобки вокруг имени функции полезны, чтобы предотвратить его расширение в виде макроса, аналогичного функции, с тем же именем. Например, функции isxxx
в ctype.h
определяются как обе функции и макросы. Это значит, что вы можете взять указатель на isalpha
. Но как библиотека C определяет out-of-line isalpha
? Наверное, вот так:
#include <ctype.h>
int
(isalpha)(int c)
{
return isalpha(c);
}
Использование isalpha
в теле функции расширяется как макрос, использование в заголовке функции не является.
1 #include <stdio.h>
2
3
4 typedef int (fc_name)(void);
5
6
7
8 int test_func1 ()
9 {
10 printf("\n test_func1 called\n");
11
12 return 0;
13 }
14
15 int test_func2 (void)
16 {
17 printf("\n test_func2 called\n");
18 return 0;
19 }
20
21 int handler_func(fc_name *fptr)
22 {
23 //Call the actual function
24 fptr();
25 }
26
27 int main(void)
28 {
29 fc_name *f1, *f2;
30
31 f1 = test_func1;
32 f2 = test_func2;
33
34 handler_func(f1);
35 handler_func(f2);
36
37 printf("\n test complete\n");
38
39 return 0;
40 }
ВЫХОД:-
test_func1 called
test_func2 called
test complete
Таким образом, typedef, о котором я спрашивал, (строка # 4 здесь) представляет тип функции и не совпадает с указателем функции typedef. Этот тип typedef не имеет большого значения. Они используются в качестве стандарта стиля или просто для намеренного создания запутывания ;-)
Правильная форма:
typedef int (*myfunc)(void);
Вы можете определить функцию, как показано ниже:
int helloword(void) {
printf("hello, world\n");
}
а затем определите переменную точку для этой функции:
myfunc hw_func;
hw_func = helloworld;
и вызовите функцию указателем функции:
int ret = (*hw_func)();
Причина, по которой нам нужен указатель на функцию, заключается в том, что язык C не имеет предопределенного указателя функции и использует указатель void *
для вызова функции на C-языке.