2013-09-23 14 views
10

Mam następujący kod, który skompilować z gcc#define i #include zamówienie w C

#include<stdio.h> 
#include<stdbool.h> 
#define true 9 
int main() { 
    printf("TRUE = %d\n",true); 
    return 0; 
} 

i dostaję błąd

test.c:3:0: warning: "true" redefined [enabled by default] 
In file included from test.c:2:0: 
/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdbool.h:34:0: note: this is the location of the previous definition 

Ale kiedy zmienić kod trochę

#include<stdio.h> 
#define true 9 
#include<stdbool.h> 
int main() { 
    printf("TRUE = %d\n",true); 
    return 0; 
} 

Wyjście:

TRUE = 1 

Pytanie:

rozumiem przyczynę błędu w pierwszym przypadku, lecz w drugim przypadku, gdy określenie true zanim #include<stdbool.h>, dlaczego jest możliwość przedefiniowania true?

Aktualizacja:

Oto stdbool.h.

pierwszych kilku liniach są

#ifndef _STDBOOL_H 
#define _STDBOOL_H 

#ifndef __cplusplus 

#define bool _Bool 
#define true 1 
#define false 0 

który ma jak w Yu Hao „s answer.

+4

Mam nadzieję, że nie myślisz poważnie o zdefiniowaniu prawdziwej – Bathsheba

+2

@Bathsheba Myślę, że OP robi test, więc potrzebuje innej wartości niż '1', aby zobaczyć, które makro działa. –

Odpowiedz

7

Chociaż Yu Hao dał possible answer na pytanie, rzeczy rzeczywiście są różne tutaj.

Łatwo to udowodnić, zaglądając do stdbool.h, aby zdać sobie sprawę, że nie ma "strażnika" #ifdef ... #endif wokół definicji true.

Co więcej gcc po prostu przestaje wyświetlać ostrzeżenia, które mogą być zgłaszane w przypadku problemów z nagłówkami systemu: * 1.

Użyj opcji gcc w opcji -isystem, aby pierwszy przykład zachowywał się jak drugi.

From the gcc manual:

Pliki nagłówkowe deklarujące interfejsy do systemu operacyjnego i biblioteki uruchomieniowe często nie mogą być zapisane w ściśle zgodny C. Dlatego GCC daje kod znaleźć w systemie nagłówki specjalnego traktowania. Wszystkie ostrzeżenia, inne niż te generowane przez "#warning" (patrz Diagnostyka), są pomijane, podczas gdy GCC przetwarza nagłówek systemu. Makra zdefiniowane w nagłówku systemu są odporne na kilka ostrzeżeń, niezależnie od tego, gdzie są rozwijane. Ta odporność jest przyznawana na zasadzie ad-hoc, gdy stwierdzimy, że ostrzeżenie generuje wiele fałszywych alarmów z powodu kodu w makrach zdefiniowanych w nagłówkach systemu.

[...]

Opcja wiersza poleceń -isystem dodaje swój argument do listy katalogów zawierających nagłówki, podobnie jak -I. Wszelkie nagłówki znalezione w tym katalogu będą uważane za nagłówki systemowe.


* 1: nagłówki nagłówki systemowe są zawarte w nawiasach <>.

+0

Hmm "-isystem' nie wydaje mi się generować ostrzeżenia w' gcc' ale +1 to jest lepsze wytłumaczenie. –

+0

@ShafikYaghmour: Sry, pomieszałem to. Zobacz moją poprawioną odpowiedź. – alk

+0

@alk Brak błędu z powodu ostrzeżenia o zaniku, ponieważ "GCC podaje kod znajdujący się w nagłówkach systemowych specjalnego traktowania."? – TheKojuEffect

9

W pliku stdbool.h, kod może wyglądać następująco:

#ifdef true 
#undef true 
#define true 1 
#endif 

powinien zrobić to samo, gdy makro mogą być zdefiniowane wcześniej. Inny podobny trik jest tak:

#ifndef MAGIC 
#define MAGIC 42 
#endif 

EDIT

Okazuje się, że to jest gcc's feature patrz @alk's answer o szczegóły.

Wszystkie ostrzeżenia, inne niż te generowane przez "#warszowanie", są pomijane, podczas gdy GCC przetwarza nagłówek systemu. Makra zdefiniowane w nagłówku systemu są odporne na kilka ostrzeżeń, niezależnie od tego, gdzie są rozwijane.

+2

Cóż, musi to być '# ifdef', a następnie' # undef', ponieważ w drugim przykładzie wartość 'stdbool.h' jest wypisywana zamiast instrukcji' # define'. – svk

+0

@YuHao Sprawdź moje zaktualizowane pytanie. – TheKojuEffect

+2

"* ... kod może wyglądać jak ... *": ale tak nie jest. Proszę zobaczyć moją odpowiedź na to pytanie. – alk

-1

dobrze, ostrzeżenie już mówi:

test.c:3:0: warning: "true" redefined [enabled by default] 

GCC pozwala przedefiniować wartości, chyba że wyraźnie powiedzieć, że nie będzie. Możesz użyć -Werror do tego.

Powiązane problemy