2013-09-23 32 views
10

Tôi đã mã sau đây mà tôi biên dịch với gcc#define và trật tự #include trong C

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

Và tôi nhận được Lỗi

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 

Nhưng khi tôi thay đổi mã một chút

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

Đầu ra:

TRUE = 1 

Câu hỏi:

Tôi hiểu lý do lỗi trong trường hợp đầu tiên nhưng trong trường hợp thứ hai khi tôi xác định true trước khi tôi #include<stdbool.h>, tại sao là nó cho phép để xác định lại true?

Cập nhật:

Đây là stdbool.h.

vài dòng đầu tiên là

#ifndef _STDBOOL_H 
#define _STDBOOL_H 

#ifndef __cplusplus 

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

đó là gì, như thế nào trong 's answer Yu Hao.

+4

Tôi hy vọng bạn không nghiêm túc suy nghĩ về việc xác định đúng – Bathsheba

+2

@Bathsheba Tôi nghĩ rằng OP đang thực hiện thử nghiệm, vì vậy, anh ta cần giá trị khác với '1' để xem macro nào đang hoạt động. –

Trả lời

7

Mặc dù Yu Hao đã đưa ra một câu hỏi possible answer, mọi thứ thực sự khác nhau ở đây.

Điều này dễ dàng có thể được chứng minh bằng cách xem xét stdbool.h để nhận ra rằng không có #ifdef ... #endif "bảo vệ" xung quanh định nghĩa của true.

Hơn nữa, gcc chỉ đơn giản là nhấn mạnh cảnh báo mà không được đưa ra cho các sự cố trong tiêu đề hệ thống * 1.

Sử dụng tùy chọn của gcc -isystem để làm ví dụ đầu tiên hoạt động như số 2.

From the gcc manual:

Các tập tin tiêu đề tuyên bố giao diện cho hệ điều hành và các thư viện runtime thường không thể được viết bằng phù hợp chặt chẽ C. Do đó, GCC cho mã được tìm thấy trong hệ thống tiêu đề đối xử đặc biệt. Tất cả các cảnh báo, trừ những cảnh báo được tạo bởi ‘#warning’ (xem Chẩn đoán), bị chặn trong khi GCC đang xử lý tiêu đề hệ thống. Macro được xác định trong tiêu đề hệ thống miễn nhiễm với một vài cảnh báo ở bất kỳ nơi nào chúng được mở rộng. Khả năng miễn dịch này được cấp trên cơ sở đặc biệt, khi chúng tôi thấy rằng một cảnh báo tạo ra rất nhiều xác thực sai vì mã trong các macro được xác định trong tiêu đề hệ thống.

[...]

Các tùy chọn dòng lệnh -isystem thêm đối số của nó vào danh sách các thư mục để tìm kiếm tiêu đề, giống như -I. Bất kỳ tiêu đề nào được tìm thấy trong thư mục đó sẽ được coi là tiêu đề hệ thống.


* 1: tiêu đề hệ thống là tiêu đề bao gồm trong <> dấu ngoặc đơn.

+0

Hmm '-isystem' dường như không tạo ra cảnh báo cho tôi trong' gcc' nhưng +1 đây là giải thích tốt hơn. –

+0

@ShafikYaghmour: Sry, tôi trộn nó lên. Vui lòng xem câu trả lời đã sửa của tôi. – alk

+0

@alk Không có lỗi do cảnh báo bị chặn bởi vì "GCC cung cấp mã được tìm thấy trong tiêu đề hệ thống xử lý đặc biệt". – TheKojuEffect

9

Trong tập tin stdbool.h, mã có thể trông như thế này:

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

Bạn nên làm điều tương tự khi vĩ mô có thể được định nghĩa trước. Một thủ thuật tương tự là như thế này:

#ifndef MAGIC 
#define MAGIC 42 
#endif 

EDIT

Hóa ra là gcc's feature này, xem @alk's answer để xem chi tiết.

Tất cả cảnh báo, ngoại trừ cảnh báo được tạo bởi ‘#warning’, bị chặn trong khi GCC xử lý tiêu đề hệ thống. Macro được xác định trong tiêu đề hệ thống miễn nhiễm với một vài cảnh báo ở bất kỳ nơi nào chúng được mở rộng.

+2

Vâng, nó sẽ phải là '# ifdef' rồi' # undef', vì trong ví dụ thứ hai, giá trị từ 'stdbool.h' được in chứ không phải là' # define' thủ công. – svk

+0

@YuHao Kiểm tra câu hỏi đã cập nhật của tôi. – TheKojuEffect

+2

"* ... mã có thể trông giống như ... *": nhưng không. Vui lòng xem câu trả lời của tôi cho câu hỏi này. – alk

-1

Vâng, cảnh báo của bạn đã nói nó:

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

GCC cho phép bạn xác định lại giá trị trừ khi bạn rõ ràng nói với nó không. Bạn có thể sử dụng -Werror cho việc này.