2013-09-01 3 views
2

Как работает следующий код без указания имени для typedef в третьей строке? Как компилятор предполагает pf как новый тип данных?Объявление typedef функции

#include <stdio.h> 

int fun(int, int); 
typedef int (*pf) (int, int); 
int proc(pf, int, int); 

int main(){ 
    printf("%d\n", proc(fun, 6, 6)); 
    return 0; 
} 

int fun(int a, int b){ 
    return (a==b); 
} 

int proc(pf p, int a, int b){ 
    return ((*p)(a, b)); 
} 
+0

pf - это имя указателя на функцию;) –

+0

Я думаю, что здесь задается вопрос: «Что такое правила *, для чего typedef рассматривает псевдоним. IOW, 'typedef int int32' считает int32 псевдоним. Каковы правила, которые в функции typedef выше того, что 2 из 4 параметров считаются псевдонимом? – Duck

+0

, если вы пишете 'typedef int * name', то' name' является псевдонимом для типа ('int *'), в случае указателя функции это выглядит немного сложнее, но это тот же принцип. –

ответ

2

Синтаксически, typedef рассматривается как спецификатор класса хранения, например extern или static. Он не определяет класс хранения; это просто определено для удобства. Таким образом, вы можете заменить typedef на static и получить объявление с другим смыслом, но похожим синтаксисом и определением того же идентификатора.

У вас есть:

typedef int (*pf) (int, int); 

Замена typedef на static дает:

static int (*pf) (int, int); 

который объявляет указатель на функцию с именем pf. Версия декларации typedef также объявляет идентификатор pf, но как имя типа, а не как объект-указатель.

Имейте в виду, что typedef не создает новый тип, просто новое имя для существующего типа.Вместо объявления pf в качестве объекта объявление typedef делает pf псевдоним для имени типа int (*)(int, int).

Поскольку класс хранения спецификаторы являются необязательными, вы также можете понять сложную typedef декларации, опуская слово typedef:

int (*pf) (int, int); 

который декларирует pf как объект типа int (*) (int, int).

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

$ cdecl 
Type `help' or `?' for help 
cdecl> explain typedef int (*pf) (int, int); 
syntax error 
cdecl> explain int (*pf) (int, int); 
declare pf as pointer to function (int, int) returning int 
cdecl> 

Если у вас нет программы cdecl установленные в вашей системе, есть интернет-версия на http://cdecl.org/

7

Это даст ему имя:

typedef int (*pf) (int, int); 
       ^^ 

Это typedef'd имя. Он читается как: pf является указателем на функцию, которая принимает два int и возвращает int.

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

2

pf выступает в качестве псевдонима для функции, которая принимает два int S в качестве аргумента и возвращает a int.

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

0

Объявление typedef имеет имя - «pf». И он представляет собой указатель на функцию (вместо указания на данные, он указывает на исполняемый код в памяти).

При объявлении указателей функций typedef не следует (обычно) шаблону - «typedef oldTypeName newAliasName». Скорее, псевдоним (т. Е. Pf в приведенном выше примере) появляется между типом возвращаемого значения (слева) и типами аргументов (справа).

1

pf как typedef - это определение типа; он определяет подпись функции (что нужно указать в качестве аргументов и что она вернет). Для функции proc с использованием p в качестве переменной; он определяет «контракт» при выполнении этой функции по адресу p; этот контракт может быть проверен только во время компиляции, потому что в основном во время выполнения переменная p является только адресом.