2011-12-30 20 views
25

Hôm nay tôi stumbled khi một lỗi biên dịch khá thú vị:Lý do có số nhận dạng không được đặt trước như macro tích hợp trong gcc là gì?

int main() { 
    int const unix = 0; // error-line 
    return unix; 
} 

Cung cấp thông báo sau với gcc 4.3.2 (có, cổ ...):

error: expected unqualified-id before numeric constant 

mà chắc chắn là khá khó hiểu.

May mắn thay, kêu vang (3.0) là hữu ích hơn một chút (như thường lệ):

error: expected unqualified-id 
    int const unix = 0 
      ^
<built-in>:127:14: note: expanded from: 
#define unix 1 
      ^

Tôi chắc chắn không mong đợi unix, mà không phải được viết bằng chữ hoa hay bắt đầu với dấu gạch dưới là một vĩ mô , đặc biệt là tích hợp sẵn.

Tôi đã kiểm tra các macro được xác định trước trong gcc và có 2 (trên nền tảng của tôi) mà sử dụng "ưa thổ lộ" biểu tượng:

$ g++ -E -dM - < /dev/null | grep -v _ 
#define unix 1 
#define linux 1 

Tất cả những người khác đang "well-behaved" macro với dấu gạch hàng đầu, sử dụng định danh truyền thống dành riêng, mẫu:

#define __linux 1 
#define __linux__ 1 
#define __gnu_linux__ 1 

#define __unix__ 1 
#define __unix 1 

#define __CHAR_BIT__ 8 
#define __x86_64 1 
#define __amd64 1 
#define _LP64 1 

(đó là một mớ hỗn độn và có dường như không có bất kỳ thứ tự cụ thể ...)

Bên cạnh đó, có rất nhiều "tương tự" biểu tượng, vì vậy tôi đoán có vấn đề về tính tương thích ngược ...

Vì vậy, các macro unixlinux đến từ đâu?

+0

Hoạt động tốt trong gcc 4.7, có vẻ như một số lỗi :) –

+0

@ Mr.Anubis: Ah tốt, tôi đang sử dụng gcc 4.3.2 (tại nơi làm việc). –

+1

Tôi đã thêm thẻ lịch sử, tôi tin rằng đó là lịch sử ít nhất. – Xeo

Trả lời

19

gcc không hoàn toàn phù hợp với bất kỳ tiêu chuẩn C nào theo mặc định.

Gọi điện thoại với -ansi, -std=c99 hoặc -std=c1xunix sẽ không được xác định trước. (-std=c1x có thể sẽ trở thành trở thành -std=c11 trong một tương lai hơn phiên bản gcc gần đây.)

Đó là một chút bối rối rằng đây là tài liệu trong cuốn hướng dẫn riêng cho preprocessor GNU, không trong cuốn hướng dẫn gcc.

Trích dẫn tài liệu GNU preprocessor (info cpp, phiên bản 4.5):

The C standard requires that all system-specific macros be part of the "reserved namespace". All names which begin with two underscores, or an underscore and a capital letter, are reserved for the compiler and library to use as they wish. However, historically system-specific macros have had names with no special prefix; for instance, it is common to find `unix' defined on Unix systems. For all such macros, GCC provides a parallel macro with two underscores added at the beginning and the end. If `unix' is defined, `__unix__' will be defined too. There will never be more than two underscores; the parallel of `_mips' is `__mips__'.

When the `-ansi' option, or any `-std' option that requests strict conformance, is given to the compiler, all the system-specific predefined macros outside the reserved namespace are suppressed. The parallel macros, inside the reserved namespace, remain defined.

We are slowly phasing out all predefined macros which are outside the reserved namespace. You should never use them in new programs, and we encourage you to correct older code to use the parallel macros whenever you find it. We don't recommend you use the system-specific macros that are in the reserved namespace, either. It is better in the long run to check specifically for features you need, using a tool such as `autoconf'.

Phiên bản hiện tại của cuốn cẩm nang là here.

+0

Tuyệt vời, vì vậy nó thực sự là lịch sử! Tôi có quyền hạn nhận thức! :) +1 – Xeo

+1

@Xeo: Nhận thức sau khi thực tế? Bây giờ đó là một siêu cường tôi muốn có! –

+0

Tại sao? Tôi đã thêm thẻ từ lâu cho câu hỏi. : P – Xeo

Các vấn đề liên quan