2013-06-26 1 views
2

Почему здесь используется три * здесь? (Glibc исходный код Glibc-2,9/sysdeps/маш/бит/Libc-lock.h линия 81)Почему используется три * в glibc libc-lock.h?

онлайн просмотр Libc-lock.h код ->http://www.oschina.net/code/explore/glibc-2.9/sysdeps/mach/bits/libc-lock.h

/* Start a critical region with a cleanup function */ 
#define __libc_cleanup_region_start(DOIT, FCT, ARG)    \ 
{                \ 
    typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0;   \ 
    typeof (ARG) __save_ARG = ARG;        \ 
/* close brace is in __libc_cleanup_region_end below. */ 

/* End a critical region started with __libc_cleanup_region_start. */ 
#define __libc_cleanup_region_end(DOIT)       \ 
if ((DOIT) && __save_FCT != 0)         \ 
    (*__save_FCT)(__save_ARG);         \ 
} 

Я не знаю, почему использование 3 * здесь, почему нет

typeof (*(FCT)) * __save_FCT = (DOIT) ? (FCT) : 0; 

Заранее спасибо.

+0

Потому что это означает что-то другое, возможно? –

+2

Возвращает ли указатель указателю на указатель? – Neil

+0

Если я не ошибаюсь при указании как одного указателя, вы можете получить предупреждения компилятора при использовании '__save_FCT'. потому что, когда 'FCT' имеет тип' ****', '__save_FCT', как ожидается, будет единственным указателем. В противном случае, если задано как '(* (FCT)),' __save_FCT' станет тройным указателем. - его догадывается. – VoidPointer

ответ

1

Я бы предположил, что это поможет гарантировать, что FCT является указателем на функцию. Когда указатель функции разыменовывается, он возвращает «обозначение функции». C99 6.5.3.2/4 «Операторы адреса и косвенности» говорит:

Оператор унарного * обозначает косвенное обозначение. Если операнд указывает на функцию, результатом является назначение функции

И так же, как и имена массивов, указатель функции оценивает указатель на функцию, за исключением случаев с несколькими парами. C99 6.3.2.1/4 «Значения, массивы и функции»:

Обозначение функции - это выражение, имеющее тип функции. За исключением случаев, когда он является операндом оператора sizeof или унарного оператора &, обозначение функции с типом «возвращающий функцию типа» преобразуется в выражение, которое имеет тип «указатель на функцию возвращаемого типа».

Поэтому вы можете произвольно разыменовать указатель на функцию (или имя функции) и по-прежнему в конечном итоге обозначать «возвращающий функцию тип».

Так что я думаю, что тройной deref должен заставить компилятор жаловаться, если для аргумента макроса FCT используется нечто иное, кроме указателя функции.

+0

Спасибо большое :) Если да, то это должно быть: typeof (*** (FCT)) * __ save_FCT = (DOIT)? (** (FCT)): 0; // 2 deref до последнего FCT ?? –

+0

Я нашел чек в комментариях 11 лет назад -> http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=4ffd4002c7282cfe84f394a93fb5ad082be1820f 'синтаксис, так что функции и аргументы указателя на функцию работают правильно ' –

+0

@zhao_x_g: хорошая находка (я думал о попытке выкопать «вину» за этот набор кода, но решил, что я слишком ленив, чтобы попробовать). Таким образом, похоже, что изменение использует преимущество, о котором я говорю, но имеет другую мотивацию. –

Смежные вопросы