2012-10-02 18 views
7

Najnowsze wersje gcc i brzękiem na Fedora Linux skompilować następujący program bez błędów:Wywołanie funkcji w instrukcji if bez nawiasów

#include <ctype.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) { 
    char c = 'a'; 
    if islower(c) 
     printf("%d", c); 
    else 
     printf("%c", c); 
    return 0; 
} 

To z gcc 4.7.2 i brzękiem 3.0. Na moim Macu, przeciwnie, zarówno gcc 4.2.1, jak i Apple clang 4.1 narzekają na brakujące nawiasy w linii "if islower (c)", zgodnie z oczekiwaniami. We wszystkich przypadkach uruchomiłem kompilatory za pomocą "-std = c99".

Czy to błąd w najnowszych wersjach gcc i clang, dziwactwo w języku C, czy coś innego? Standard C99 (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf s. 133) wydaje się nawiązywać do nawiasów wokół wyrażenia we wszystkich przypadkach.

+0

Czy skompiluje 'jeśli 42 printf (" 42! \ N ");'? Jeśli tak, jest to interesujące podejście do wyrażeń. Formalnie, jeśli zapomnimy o 'if',' 42' i '(42)' są identyczne. Ditto z 'islower (c)' and '(islower (c))'. –

+0

Alexey, to nie do końca prawda, ponieważ gramatyka C wymaga nawiasów w tym konkretnym kontekście. Tak się składa, że ​​nawiasy są tutaj dostarczane przez makro. –

+0

Jelle, dlatego powiedziałem: "to ciekawe podejście do wyrażeń", ponieważ zgodnie z moją wiedzą, pareny są wymagane. –

Odpowiedz

10

Właśnie przejrzałem pliku ctype.h znajduje się w /usr/include/ctype.h i znaleźć następującą definicję dla islower:

#define islower(c) __isctype((c), _ISlower) 

przechodząc do definicji dla __isctype() znajdę:

#define __isctype(c, type) \ 
    ((*__ctype_b_loc())[(int) (c)] & (unsigned short int) type) 

więc kod if islower(c) rozszerza na:

if ((*__ctype_b_loc())[(int) (c)] & (unsigned short int) _ISlower) 

Który, jak powiedział unwind, dodał nawias podczas ekspansji.

+0

zrelaksować się i masz rację, dzięki! Powinienem był się domyślić, że tak właśnie było. gcc -E daje "if ((* __ ctype_b_loc()) [(int) ((m))] & (unsigned short int) _ISalpha)", jak powiedziałeś. –

13

Jest prawdopodobne, że islower() jest makro, a rozszerzenie dodaje nawias.

Publikuj wstępnie przetworzone dane wyjściowe z GCC, które można uzyskać, kompilując je za pomocą opcji -E.

Powiązane problemy