ทำไมตัวประมวลผลล่วงหน้า C ตีความคำว่า“ linux” เป็นค่าคงที่“ 1”


1022

ทำไมCตัวประมวลผลล่วงหน้าในGCCตีความคำว่าlinux(ตัวอักษรตัวเล็ก) เป็นค่าคงที่1?

test.c:

#include <stdio.h>
int main(void)
{       
    int linux = 5;
    return 0;
}

ผลลัพธ์ของ $ gcc -E test.c (หยุดหลังจากขั้นตอนการประมวลผลล่วงหน้า):

....
int main(void)
{
    int 1 = 5;
    return 0;
}

ซึ่งแน่นอนว่าข้อผิดพลาด

(BTW: ไม่มี#define linuxในstdio.hไฟล์)


52
คุณคิดว่าคำถาม / ปัญหานี้จะเกิดขึ้นแล้วในตอนนี้
Letseatlunch

1
คำถามที่เกี่ยวข้อง: stackoverflow.com/questions/3770322/…
matcheek

14
คุณได้ลอง#undef linuxหรืออาจใช้ตัวแปรอื่น ฉันคิดว่าค่าคงที่linuxนั้นใช้สำหรับทดสอบระบบปฏิบัติการเช่นถ้าคุณกำลังออกแบบแอพพลิเคชั่นข้ามแพลตฟอร์มและจำเป็นต้องรู้ว่า API ใดที่จะใช้ (windows, mac, linux, BSD, ฯลฯ ) มันไม่ได้อยู่ใน stdio.h แต่ก็ยังคงถูกกำหนดถ้าเคอร์เนลเป็นลินุกซ์ รหัสเดียวกันไม่ควรเกิดข้อผิดพลาดใน Windows แต่ใช้บางอย่างเช่น windows หรือ WINDOWS เป็นตัวแปรอาจจะและในทางกลับกัน
Braden Best

แค่อยากรู้อยากเห็น: จะเกิดอะไรขึ้นโดยการเพิ่มพารามิเตอร์บรรทัดคำสั่ง -Ulinux ในการรวบรวม?
dhein

1
@BradenBest _WIN32 และเมทริกซ์ที่คล้ายกัน
พอลสเตเลียน

คำตอบ:


955

ใน Old Days (pre-ANSI) การกำหนดสัญลักษณ์ล่วงหน้าเช่นunixและvaxเป็นวิธีการที่อนุญาตให้โค้ดตรวจจับได้ในเวลารวบรวมซึ่งระบบที่ถูกรวบรวมไว้ ในตอนนั้นไม่มีมาตรฐานภาษาทางการ (นอกเหนือจากเอกสารอ้างอิงที่อยู่ด้านหลังของรุ่นแรกของ K&R) และรหัส C ของความซับซ้อนใด ๆ โดยทั่วไปจะเป็นเขาวงกตที่ซับซ้อนของ#ifdefs เพื่อให้เกิดความแตกต่างระหว่างระบบ นิยามแมโครเหล่านี้มักถูกตั้งค่าโดยคอมไพเลอร์เองโดยไม่ได้กำหนดไว้ในไฟล์ส่วนหัวของไลบรารี เนื่องจากไม่มีกฎที่แท้จริงเกี่ยวกับตัวระบุที่สามารถนำมาใช้โดยการดำเนินการและที่สงวนไว้สำหรับโปรแกรมเมอร์นักเขียนคอมไพเลอร์รู้สึกอิสระที่จะใช้ชื่อง่าย ๆ เช่นunixและสันนิษฐานว่าโปรแกรมเมอร์จะหลีกเลี่ยงการใช้ชื่อเหล่านั้นเพื่อจุดประสงค์ของตนเอง

มาตรฐาน ANSI C ปี 1989 แนะนำกฎที่ จำกัด สัญลักษณ์ที่การใช้งานสามารถกำหนดไว้ล่วงหน้าตามกฎหมาย แมโครที่คอมไพเลอร์กำหนดไว้ล่วงหน้าสามารถมีชื่อขึ้นต้นด้วยเครื่องหมายขีดล่างสองอันหรือขีดล่างตามด้วยตัวอักษรตัวพิมพ์ใหญ่ปล่อยให้โปรแกรมเมอร์อิสระที่จะใช้ตัวระบุที่ไม่ตรงกับรูปแบบนั้นและไม่ได้ใช้ในไลบรารีมาตรฐาน

เป็นผลให้คอมไพเลอร์ใด ๆ ที่กำหนดไว้ล่วงหน้าunixหรือจะไม่สอดคล้องเพราะมันจะล้มเหลวในการรวบรวมรหัสสมบูรณ์ตามกฎหมายที่ใช้สิ่งที่ต้องการlinuxint linux = 5;

เมื่อมันเกิดขึ้น gcc จะไม่สอดคล้องตามค่าเริ่มต้น - แต่มันสามารถทำเพื่อให้เข้ากันได้ดีพอสมควรด้วยตัวเลือกบรรทัดคำสั่งที่ถูกต้อง:

gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic

ดูคู่มือ gccสำหรับรายละเอียดเพิ่มเติม

gcc จะยกเลิกคำจำกัดความเหล่านี้ในรุ่นอนาคตดังนั้นคุณไม่ควรเขียนโค้ดที่ขึ้นอยู่กับพวกเขา หากโปรแกรมของคุณจำเป็นต้องรู้ว่ามันถูกรวบรวมเพื่อเป้าหมาย Linux หรือไม่ก็สามารถตรวจสอบได้ว่า__linux__มีการกำหนดไว้ (สมมติว่าคุณใช้ gcc หรือคอมไพเลอร์ที่เข้ากันได้กับมัน) ดูคู่มือผู้ประมวลผลก่อน GNU Cสำหรับข้อมูลเพิ่มเติม

สิ่งที่ไม่เกี่ยวข้องส่วนใหญ่: ผู้ชนะรางวัล "Best One Liner" จากการประกวดรหัส C ระหว่างประเทศปี 2530 โดย David Korn (ใช่ผู้เขียน Korn Shell) ใช้ประโยชน์จากunixมาโครที่กำหนดไว้ล่วงหน้า:

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}

มันพิมพ์"unix"แต่ด้วยเหตุผลที่ไม่มีอะไรเกี่ยวข้องกับการสะกดชื่อแมโคร


32
@ เซบาสเตียน: ฉันไม่ต้องการที่จะโพสต์สปอยเลอร์ใด ๆ ที่นี่และฉันขอแนะนำให้ทุกคนที่อ่านนี้เพื่อพยายามที่จะเข้าใจรหัสด้วยตัวเองก่อน แต่ถ้าคุณอยากจะยอมแพ้จริงๆฉันได้โพสต์คำอธิบาย: gist.github.com/Keith-S-Thompson/6920347
Keith Thompson

10
คำใบ้ที่กล่าวถึงโดย @robbie_c ได้ย้ายมาที่นี่แล้ว: ioccc.org/1987/korn/hint.html
Ingo Blechschmidt

7
"ในสมัยก่อน (pre-ANSI) สัญลักษณ์ที่กำหนดไว้ล่วงหน้าเช่นunixและvax" - หือ? มันเป็นความเข้าใจของฉันที่ในสมัยโบราณโลกทั้งใบเป็นvax!
sqweek

6
ฉันคิดว่ามันเป็นไข่อีสเตอร์ แต่มันกลับกลายเป็นไดโนเสาร์
Rolf

2
@ KeithThompson กลับกลายเป็นว่ามีพฤติกรรมที่ไม่ได้กำหนดจริงๆในตัวอย่างข้อมูลนั้น (แม้ว่าจะไม่เกี่ยวข้องกับการunixกำหนด) ฉันอธิบายว่าทำไมในความเห็นเกี่ยวกับแก่นสารนั้นถ้าคุณหรือใครก็ตามมีความอยากรู้อยากเห็น
Joseph Sible-Reinstate Monica

184

สิ่งนี้ดูเหมือนจะเป็น "ส่วนขยาย GNU" (ไม่มีเอกสาร): [ การแก้ไข : ในที่สุดฉันก็พบการกล่าวถึงในเอกสาร ดูด้านล่าง]

คำสั่งต่อไปนี้ใช้-dMตัวเลือกเพื่อพิมพ์ตัวกำหนดล่วงหน้าทั้งหมด เนื่องจากอินพุต "ไฟล์" ว่างเปล่าจึงแสดงมาโครที่กำหนดไว้ล่วงหน้าทั้งหมด มันรันด้วย gcc-4.7.3 บนการติดตั้ง Ubuntu มาตรฐาน คุณจะเห็นว่าตัวประมวลผลล่วงหน้าเป็นมาตรฐานที่รับรู้ โดยรวมมี 243 แมโครที่มี-std=gnu99และ 240 ด้วย-std=c99; ฉันกรองผลลัพธ์เพื่อความเกี่ยวข้อง

$ cpp --std=c89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

$ cpp --std=gnu89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

$ cpp --std=c99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

$ cpp --std=gnu99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

รุ่น "มาตรฐาน gnu" ด้วยเช่น#define unixกัน การใช้c11และgnu11สร้างผลลัพธ์เดียวกัน)

ฉันคิดว่าพวกเขามีเหตุผลของพวกเขา แต่ดูเหมือนว่าฉันจะทำการติดตั้งเริ่มต้นของ gcc (ซึ่งรวบรวมรหัส C ด้วย -std=gnu89เว้นแต่จะระบุไว้เป็นอย่างอื่น) ไม่เป็นไปตามข้อกำหนดและ - เช่นเดียวกับในคำถามนี้ - น่าแปลกใจ ไม่อนุญาตให้สร้างเนมสเปซส่วนกลางด้วยแมโครที่มีชื่อที่ไม่ขึ้นต้นด้วยขีดล่างไม่อนุญาตให้ใช้ในการปฏิบัติตามข้อกำหนด (6.8.10p2: "ชื่อแมโครที่กำหนดไว้ล่วงหน้าอื่น ๆ จะเริ่มต้นด้วยเครื่องหมายขีดล่างนำตามด้วยตัวอักษรตัวพิมพ์ใหญ่หรือขีดล่างที่สอง" แต่ตามที่กล่าวไว้ในภาคผนวก J.5 (ปัญหาการพกพา) ชื่อดังกล่าวมักถูกกำหนดไว้ล่วงหน้า)

เมื่อตอนแรกที่ฉันเขียนคำตอบนี้ฉันไม่สามารถค้นหาเอกสารใด ๆ ใน gcc เกี่ยวกับปัญหานี้ได้ แต่ในที่สุดฉันก็ค้นพบมันไม่ใช่พฤติกรรมที่กำหนดในการนำไปใช้งาน Cหรือในส่วนขยาย Cแต่ในcppส่วน3.7.3ด้วยตนเอง มันตั้งข้อสังเกตว่า:

เรากำลังค่อย ๆ กำจัดมาโครที่กำหนดไว้ล่วงหน้าทั้งหมดซึ่งอยู่นอกเนมสเปซที่สงวนไว้อย่างช้า ๆ คุณไม่ควรใช้มันในโปรแกรมใหม่ ...


57
ไม่เป็นการละเมิดมาตรฐาน C เนื่องจากการรวบรวม GCC สำหรับ gnu89 หรือ gnu99 ไม่ใช่การดำเนินการตามมาตรฐาน C และมาตรฐาน C ไม่ได้กำหนดข้อกำหนดเกี่ยวกับสิ่งที่ไม่ได้นำไปปฏิบัติ
Eric Postpischil

17
@EricPostpischil: นั่นเป็นเรื่องจริงอย่างแน่นอน มันเป็นเพียงการดำเนินการที่ไม่สอดคล้อง อย่างไรก็ตาม -std = c89 เป็นการตั้งค่าเริ่มต้นสำหรับ gcc ดังนั้นโดยค่าเริ่มต้น gcc จะไม่สอดคล้อง แน่นอนว่าไม่ใช่เรื่องผิดกฎหมาย แต่ใคร ๆ ก็คาดหวังว่าในบางช่วงของการขยายตัว gnu89, gnu99, gnu11, gcc นั้นอาจปล่อยมลภาวะ namespace หรือบันทึกไว้ที่ใดที่หนึ่ง
rici

1
@EricPostpischil: ตกลงฉันพบเอกสารบางอย่างในเอกสาร gnu cpp ซึ่งรวมถึงประโยคที่ว่า "เรากำลังค่อย ๆ กำจัดมาโครที่กำหนดไว้ล่วงหน้าทั้งหมดซึ่งอยู่นอกเนมสเปซที่สงวนไว้อย่างช้า ๆ คุณไม่ควรใช้มันในโปรแกรมใหม่และเราแนะนำให้คุณแก้ไข รหัสที่เก่ากว่าให้ใช้มาโครแบบขนานทุกครั้งที่คุณพบ " ฉันจะแก้ไขคำตอบหลังอาหารกลางวันด้วยตัวชี้
rici

5
@EricPostpischil: คุณพูดถูก ฉันพิมพ์ผิดที่ ฉันหมายความว่า-std=gnu89เป็นค่าเริ่มต้นและเท่าที่ฉันรู้ว่ามันเป็นค่าเริ่มต้นบน Solaris, Linux และ Mac OS x ( developer.apple.com/library/mac/documentation/Darwin/Reference/ ......สำหรับรุ่นหลัง) และก็ อันที่ทำให้เนมสเปซสกปรก c89พยายามที่จะปฏิบัติตามมาตรฐานดังนั้นหากเป็นค่าเริ่มต้นฉันจะไม่ร้องเรียน
rici

6
@ChrisDodd: ฉันไม่เห็นว่ามันเป็นความคิดที่ดีหรือไม่ ฉันเชื่อมั่นว่าการเบี่ยงเบนมาตรฐานดังกล่าวควรหาได้ง่ายในเอกสารประกอบ
rici

67

เพราะlinuxเป็นมาโครในตัวที่กำหนดไว้เมื่อคอมไพเลอร์ทำงานอยู่หรือคอมไพล์ (ถ้าเป็น cross-compiler), Linux

มีมาโครที่กำหนดไว้ล่วงหน้าจำนวนมาก ด้วย GCC คุณสามารถใช้:

cp /dev/null emptyfile.c
gcc -E -dM emptyfile.c

เพื่อรับรายการแมโคร (ฉันไม่ได้โน้มน้าวให้ GCC ยอมรับ/dev/nullโดยตรง แต่ดูเหมือนว่าไฟล์เปล่าจะทำงานได้ดี) ด้วย GCC 4.8.1 ที่ทำงานบน Mac OS X 10.8.5 ฉันได้ผลลัพธ์:

#define __DBL_MIN_EXP__ (-1021)
#define __UINT_LEAST16_MAX__ 65535
#define __ATOMIC_ACQUIRE 2
#define __FLT_MIN__ 1.17549435082228750797e-38F
#define __UINT_LEAST8_TYPE__ unsigned char
#define __INTMAX_C(c) c ## L
#define __CHAR_BIT__ 8
#define __UINT8_MAX__ 255
#define __WINT_MAX__ 2147483647
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __SIZE_MAX__ 18446744073709551615UL
#define __WCHAR_MAX__ 2147483647
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#define __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L)
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
#define __FLT_EVAL_METHOD__ 0
#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
#define __x86_64 1
#define __UINT_FAST64_MAX__ 18446744073709551615ULL
#define __SIG_ATOMIC_TYPE__ int
#define __DBL_MIN_10_EXP__ (-307)
#define __FINITE_MATH_ONLY__ 0
#define __GNUC_PATCHLEVEL__ 1
#define __UINT_FAST8_MAX__ 255
#define __DEC64_MAX_EXP__ 385
#define __INT8_C(c) c
#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
#define __SHRT_MAX__ 32767
#define __LDBL_MAX__ 1.18973149535723176502e+4932L
#define __UINT_LEAST8_MAX__ 255
#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
#define __APPLE_CC__ 1
#define __UINTMAX_TYPE__ long unsigned int
#define __DEC32_EPSILON__ 1E-6DF
#define __UINT32_MAX__ 4294967295U
#define __LDBL_MAX_EXP__ 16384
#define __WINT_MIN__ (-__WINT_MAX__ - 1)
#define __SCHAR_MAX__ 127
#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
#define __INT64_C(c) c ## LL
#define __DBL_DIG__ 15
#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
#define __SIZEOF_INT__ 4
#define __SIZEOF_POINTER__ 8
#define __USER_LABEL_PREFIX__ _
#define __STDC_HOSTED__ 1
#define __LDBL_HAS_INFINITY__ 1
#define __FLT_EPSILON__ 1.19209289550781250000e-7F
#define __LDBL_MIN__ 3.36210314311209350626e-4932L
#define __DEC32_MAX__ 9.999999E96DF
#define __strong 
#define __INT32_MAX__ 2147483647
#define __SIZEOF_LONG__ 8
#define __APPLE__ 1
#define __UINT16_C(c) c
#define __DECIMAL_DIG__ 21
#define __LDBL_HAS_QUIET_NAN__ 1
#define __DYNAMIC__ 1
#define __GNUC__ 4
#define __MMX__ 1
#define __FLT_HAS_DENORM__ 1
#define __SIZEOF_LONG_DOUBLE__ 16
#define __BIGGEST_ALIGNMENT__ 16
#define __DBL_MAX__ ((double)1.79769313486231570815e+308L)
#define __INT_FAST32_MAX__ 2147483647
#define __DBL_HAS_INFINITY__ 1
#define __DEC32_MIN_EXP__ (-94)
#define __INT_FAST16_TYPE__ short int
#define __LDBL_HAS_DENORM__ 1
#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
#define __INT_LEAST32_MAX__ 2147483647
#define __DEC32_MIN__ 1E-95DF
#define __weak 
#define __DBL_MAX_EXP__ 1024
#define __DEC128_EPSILON__ 1E-33DL
#define __SSE2_MATH__ 1
#define __ATOMIC_HLE_RELEASE 131072
#define __PTRDIFF_MAX__ 9223372036854775807L
#define __amd64 1
#define __tune_core2__ 1
#define __ATOMIC_HLE_ACQUIRE 65536
#define __LONG_LONG_MAX__ 9223372036854775807LL
#define __SIZEOF_SIZE_T__ 8
#define __SIZEOF_WINT_T__ 4
#define __GXX_ABI_VERSION 1002
#define __FLT_MIN_EXP__ (-125)
#define __INT_FAST64_TYPE__ long long int
#define __DBL_MIN__ ((double)2.22507385850720138309e-308L)
#define __LP64__ 1
#define __DEC128_MIN__ 1E-6143DL
#define __REGISTER_PREFIX__ 
#define __UINT16_MAX__ 65535
#define __DBL_HAS_DENORM__ 1
#define __UINT8_TYPE__ unsigned char
#define __NO_INLINE__ 1
#define __FLT_MANT_DIG__ 24
#define __VERSION__ "4.8.1"
#define __UINT64_C(c) c ## ULL
#define __GCC_ATOMIC_INT_LOCK_FREE 2
#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
#define __INT32_C(c) c
#define __DEC64_EPSILON__ 1E-15DD
#define __ORDER_PDP_ENDIAN__ 3412
#define __DEC128_MIN_EXP__ (-6142)
#define __INT_FAST32_TYPE__ int
#define __UINT_LEAST16_TYPE__ short unsigned int
#define __INT16_MAX__ 32767
#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 1080
#define __SIZE_TYPE__ long unsigned int
#define __UINT64_MAX__ 18446744073709551615ULL
#define __INT8_TYPE__ signed char
#define __FLT_RADIX__ 2
#define __INT_LEAST16_TYPE__ short int
#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
#define __UINTMAX_C(c) c ## UL
#define __SSE_MATH__ 1
#define __k8 1
#define __SIG_ATOMIC_MAX__ 2147483647
#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
#define __SIZEOF_PTRDIFF_T__ 8
#define __x86_64__ 1
#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
#define __INT_FAST16_MAX__ 32767
#define __UINT_FAST32_MAX__ 4294967295U
#define __UINT_LEAST64_TYPE__ long long unsigned int
#define __FLT_HAS_QUIET_NAN__ 1
#define __FLT_MAX_10_EXP__ 38
#define __LONG_MAX__ 9223372036854775807L
#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
#define __FLT_HAS_INFINITY__ 1
#define __UINT_FAST16_TYPE__ short unsigned int
#define __DEC64_MAX__ 9.999999999999999E384DD
#define __CHAR16_TYPE__ short unsigned int
#define __PRAGMA_REDEFINE_EXTNAME 1
#define __INT_LEAST16_MAX__ 32767
#define __DEC64_MANT_DIG__ 16
#define __INT64_MAX__ 9223372036854775807LL
#define __UINT_LEAST32_MAX__ 4294967295U
#define __GCC_ATOMIC_LONG_LOCK_FREE 2
#define __INT_LEAST64_TYPE__ long long int
#define __INT16_TYPE__ short int
#define __INT_LEAST8_TYPE__ signed char
#define __DEC32_MAX_EXP__ 97
#define __INT_FAST8_MAX__ 127
#define __INTPTR_MAX__ 9223372036854775807L
#define __LITTLE_ENDIAN__ 1
#define __SSE2__ 1
#define __LDBL_MANT_DIG__ 64
#define __CONSTANT_CFSTRINGS__ 1
#define __DBL_HAS_QUIET_NAN__ 1
#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
#define __code_model_small__ 1
#define __k8__ 1
#define __INTPTR_TYPE__ long int
#define __UINT16_TYPE__ short unsigned int
#define __WCHAR_TYPE__ int
#define __SIZEOF_FLOAT__ 4
#define __pic__ 2
#define __UINTPTR_MAX__ 18446744073709551615UL
#define __DEC64_MIN_EXP__ (-382)
#define __INT_FAST64_MAX__ 9223372036854775807LL
#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
#define __FLT_DIG__ 6
#define __UINT_FAST64_TYPE__ long long unsigned int
#define __INT_MAX__ 2147483647
#define __MACH__ 1
#define __amd64__ 1
#define __INT64_TYPE__ long long int
#define __FLT_MAX_EXP__ 128
#define __ORDER_BIG_ENDIAN__ 4321
#define __DBL_MANT_DIG__ 53
#define __INT_LEAST64_MAX__ 9223372036854775807LL
#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
#define __DEC64_MIN__ 1E-383DD
#define __WINT_TYPE__ int
#define __UINT_LEAST32_TYPE__ unsigned int
#define __SIZEOF_SHORT__ 2
#define __SSE__ 1
#define __LDBL_MIN_EXP__ (-16381)
#define __INT_LEAST8_MAX__ 127
#define __SIZEOF_INT128__ 16
#define __LDBL_MAX_10_EXP__ 4932
#define __ATOMIC_RELAXED 0
#define __DBL_EPSILON__ ((double)2.22044604925031308085e-16L)
#define _LP64 1
#define __UINT8_C(c) c
#define __INT_LEAST32_TYPE__ int
#define __SIZEOF_WCHAR_T__ 4
#define __UINT64_TYPE__ long long unsigned int
#define __INT_FAST8_TYPE__ signed char
#define __DBL_DECIMAL_DIG__ 17
#define __FXSR__ 1
#define __DEC_EVAL_METHOD__ 2
#define __UINT32_C(c) c ## U
#define __INTMAX_MAX__ 9223372036854775807L
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#define __FLT_DENORM_MIN__ 1.40129846432481707092e-45F
#define __INT8_MAX__ 127
#define __PIC__ 2
#define __UINT_FAST32_TYPE__ unsigned int
#define __CHAR32_TYPE__ unsigned int
#define __FLT_MAX__ 3.40282346638528859812e+38F
#define __INT32_TYPE__ int
#define __SIZEOF_DOUBLE__ 8
#define __FLT_MIN_10_EXP__ (-37)
#define __INTMAX_TYPE__ long int
#define __DEC128_MAX_EXP__ 6145
#define __ATOMIC_CONSUME 1
#define __GNUC_MINOR__ 8
#define __UINTMAX_MAX__ 18446744073709551615UL
#define __DEC32_MANT_DIG__ 7
#define __DBL_MAX_10_EXP__ 308
#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
#define __INT16_C(c) c
#define __STDC__ 1
#define __PTRDIFF_TYPE__ long int
#define __ATOMIC_SEQ_CST 5
#define __UINT32_TYPE__ unsigned int
#define __UINTPTR_TYPE__ long unsigned int
#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
#define __DEC128_MANT_DIG__ 34
#define __LDBL_MIN_10_EXP__ (-4931)
#define __SIZEOF_LONG_LONG__ 8
#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
#define __LDBL_DIG__ 18
#define __FLT_DECIMAL_DIG__ 9
#define __UINT_FAST16_MAX__ 65535
#define __GNUC_GNU_INLINE__ 1
#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
#define __SSE3__ 1
#define __UINT_FAST8_TYPE__ unsigned char
#define __ATOMIC_ACQ_REL 4
#define __ATOMIC_RELEASE 3

นั่นคือ 236 แมโครจากไฟล์ว่างเปล่า เมื่อฉันเพิ่มลง#include <stdio.h>ในไฟล์จำนวนของมาโครที่กำหนดนั้นเพิ่มขึ้นเป็น 505 ซึ่งรวมถึงมาโครการระบุแพลตฟอร์มทุกประเภท


4
แน่นอนมีจำนวนมากด้วย gcc คุณสามารถรับรายชื่อดังนี้:cpp -dM < /dev/null
asveikau

2
มัน ( linux) ไม่ได้ถูกกำหนดไว้ในเครื่อง Mac OS X ของฉัน - มันไม่ได้ใช้งาน Linux (ดีมี VM ที่ใช้ Linux แต่ ... ) มันอาจถูกกำหนดโดยส่วนหัวรวมโดย<stdio.h>; การเรียกใช้ไฟล์ว่างอาจไม่เหมือนกัน
Jonathan Leffler

20
คุณไม่สามารถใช้/dev/nullเป็นไฟล์ต้นฉบับได้หาก-xไม่มีส่วนขยายดังนั้น gcc จึงไม่ทราบว่าเป็น C หรือ C ++ คุณสามารถใช้ gcc -E -dM -x c /dev/nullหรือgcc -E -dm -x c++ /dev/nullรับรายการโดยไม่ต้องสร้างไฟล์เปล่า
Chris Dodd

2
@ChrisDodd - ทำงานได้ที่นี่ หมายเหตุ: ผมบอกว่าcpp(พรีโพรเซสเซอร์) gccไม่ได้ ยังทราบผมไม่ให้มัน/dev/nullเป็นแฟ้มอินพุต แต่ฉันใช้การเปลี่ยนเส้นทางที่จะทำให้การเข้า/dev/null stdinยัง @KerrekSB: บนเครื่องเดเบียนของฉันlinuxอยู่ในรายการ
asveikau

1
ใช่มันทำได้ คุณต้องการแข่งขันเพื่อสร้างไฟล์เปล่าหลายวิธีหรือไม่? มันอาจเป็น> emptyfile.cหรือ: > emptyfile.cหรือdd if=/etc/passwd of=emptyfile.c count=0หรือ…
Jonathan Leffler

44

จากinfo gcc(เน้นที่เหมือง):

-ansi

ในโหมด C, -std=c90นี้จะเทียบเท่ากับ ในโหมด C ++ -std=c++98มันจะเทียบเท่ากับ จะปิดคุณลักษณะบางอย่างของ GCC ที่เข้ากันได้กับมาตรฐาน ISO C90 (เมื่อรวบรวมรหัส C) หรือมาตรฐาน C ++ (เมื่อรวบรวมรหัส c ++) เช่นนี้asmและtypeofคำหลักและแมโครเช่น 'ยูนิกซ์' ที่กำหนดไว้ล่วงหน้าและ 'VAX'ว่า ระบุประเภทของระบบที่คุณใช้ นอกจากนี้ยังเปิดใช้งานคุณลักษณะทริกเกอร์ ISO ที่ไม่พึงประสงค์และไม่ค่อยได้ใช้ สำหรับคอมไพเลอร์ C จะปิดใช้งานการรับรู้ความ//คิดเห็นสไตล์ C ++ เช่นเดียวกับinlineคำหลัก

(มันใช้vaxในตัวอย่างแทนที่จะเป็นlinuxเพราะเมื่อมันถูกเขียนมันอาจจะเป็นที่นิยมมากกว่า ;-)

แนวคิดพื้นฐานคือ GCC จะพยายามปฏิบัติตามมาตรฐาน ISO อย่างสมบูรณ์เมื่อมีการเรียกใช้-ansiตัวเลือก


6
ที่จะทำให้ GCC (พยายาม) ปฏิบัติตามอย่างเต็มที่คุณต้องระบุ-ansi หรือ std=cXXที่XXเป็น89, 90, 99หรือ11, และอย่างใดอย่างหนึ่งหรือ-pedantic -pedantic-errorsแม้จะเป็นเรื่องธรรมดา ดูคู่มือสำหรับรายละเอียด
Keith Thompson

8

ใช้คำสั่งนี้

gcc -dM -E - < /dev/null

เพื่อรับสิ่งนี้

    #define _LP64 1
#define _STDC_PREDEF_H 1
#define __ATOMIC_ACQUIRE 2
#define __ATOMIC_ACQ_REL 4
#define __ATOMIC_CONSUME 1
#define __ATOMIC_HLE_ACQUIRE 65536
#define __ATOMIC_HLE_RELEASE 131072
#define __ATOMIC_RELAXED 0
#define __ATOMIC_RELEASE 3
#define __ATOMIC_SEQ_CST 5
#define __BIGGEST_ALIGNMENT__ 16
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#define __CHAR16_TYPE__ short unsigned int
#define __CHAR32_TYPE__ unsigned int
#define __CHAR_BIT__ 8
#define __DBL_DECIMAL_DIG__ 17
#define __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L)
#define __DBL_DIG__ 15
#define __DBL_EPSILON__ ((double)2.22044604925031308085e-16L)
#define __DBL_HAS_DENORM__ 1
#define __DBL_HAS_INFINITY__ 1
#define __DBL_HAS_QUIET_NAN__ 1
#define __DBL_MANT_DIG__ 53
#define __DBL_MAX_10_EXP__ 308
#define __DBL_MAX_EXP__ 1024
#define __DBL_MAX__ ((double)1.79769313486231570815e+308L)
#define __DBL_MIN_10_EXP__ (-307)
#define __DBL_MIN_EXP__ (-1021)
#define __DBL_MIN__ ((double)2.22507385850720138309e-308L)
#define __DEC128_EPSILON__ 1E-33DL
#define __DEC128_MANT_DIG__ 34
#define __DEC128_MAX_EXP__ 6145
#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
#define __DEC128_MIN_EXP__ (-6142)
#define __DEC128_MIN__ 1E-6143DL
#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
#define __DEC32_EPSILON__ 1E-6DF
#define __DEC32_MANT_DIG__ 7
#define __DEC32_MAX_EXP__ 97
#define __DEC32_MAX__ 9.999999E96DF
#define __DEC32_MIN_EXP__ (-94)
#define __DEC32_MIN__ 1E-95DF
#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
#define __DEC64_EPSILON__ 1E-15DD
#define __DEC64_MANT_DIG__ 16
#define __DEC64_MAX_EXP__ 385
#define __DEC64_MAX__ 9.999999999999999E384DD
#define __DEC64_MIN_EXP__ (-382)
#define __DEC64_MIN__ 1E-383DD
#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
#define __DECIMAL_BID_FORMAT__ 1
#define __DECIMAL_DIG__ 21
#define __DEC_EVAL_METHOD__ 2
#define __ELF__ 1
#define __FINITE_MATH_ONLY__ 0
#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
#define __FLT_DECIMAL_DIG__ 9
#define __FLT_DENORM_MIN__ 1.40129846432481707092e-45F
#define __FLT_DIG__ 6
#define __FLT_EPSILON__ 1.19209289550781250000e-7F
#define __FLT_EVAL_METHOD__ 0
#define __FLT_HAS_DENORM__ 1
#define __FLT_HAS_INFINITY__ 1
#define __FLT_HAS_QUIET_NAN__ 1
#define __FLT_MANT_DIG__ 24
#define __FLT_MAX_10_EXP__ 38
#define __FLT_MAX_EXP__ 128
#define __FLT_MAX__ 3.40282346638528859812e+38F
#define __FLT_MIN_10_EXP__ (-37)
#define __FLT_MIN_EXP__ (-125)
#define __FLT_MIN__ 1.17549435082228750797e-38F
#define __FLT_RADIX__ 2
#define __FXSR__ 1
#define __GCC_ASM_FLAG_OUTPUTS__ 1
#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
#define __GCC_ATOMIC_INT_LOCK_FREE 2
#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
#define __GCC_ATOMIC_LONG_LOCK_FREE 2
#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
#define __GCC_HAVE_DWARF2_CFI_ASM 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
#define __GCC_IEC_559 2
#define __GCC_IEC_559_COMPLEX 2
#define __GNUC_MINOR__ 3
#define __GNUC_PATCHLEVEL__ 0
#define __GNUC_STDC_INLINE__ 1
#define __GNUC__ 6
#define __GXX_ABI_VERSION 1010
#define __INT16_C(c) c
#define __INT16_MAX__ 0x7fff
#define __INT16_TYPE__ short int
#define __INT32_C(c) c
#define __INT32_MAX__ 0x7fffffff
#define __INT32_TYPE__ int
#define __INT64_C(c) c ## L
#define __INT64_MAX__ 0x7fffffffffffffffL
#define __INT64_TYPE__ long int
#define __INT8_C(c) c
#define __INT8_MAX__ 0x7f
#define __INT8_TYPE__ signed char
#define __INTMAX_C(c) c ## L
#define __INTMAX_MAX__ 0x7fffffffffffffffL
#define __INTMAX_TYPE__ long int
#define __INTPTR_MAX__ 0x7fffffffffffffffL
#define __INTPTR_TYPE__ long int
#define __INT_FAST16_MAX__ 0x7fffffffffffffffL
#define __INT_FAST16_TYPE__ long int
#define __INT_FAST32_MAX__ 0x7fffffffffffffffL
#define __INT_FAST32_TYPE__ long int
#define __INT_FAST64_MAX__ 0x7fffffffffffffffL
#define __INT_FAST64_TYPE__ long int
#define __INT_FAST8_MAX__ 0x7f
#define __INT_FAST8_TYPE__ signed char
#define __INT_LEAST16_MAX__ 0x7fff
#define __INT_LEAST16_TYPE__ short int
#define __INT_LEAST32_MAX__ 0x7fffffff
#define __INT_LEAST32_TYPE__ int
#define __INT_LEAST64_MAX__ 0x7fffffffffffffffL
#define __INT_LEAST64_TYPE__ long int
#define __INT_LEAST8_MAX__ 0x7f
#define __INT_LEAST8_TYPE__ signed char
#define __INT_MAX__ 0x7fffffff
#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
#define __LDBL_DIG__ 18
#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
#define __LDBL_HAS_DENORM__ 1
#define __LDBL_HAS_INFINITY__ 1
#define __LDBL_HAS_QUIET_NAN__ 1
#define __LDBL_MANT_DIG__ 64
#define __LDBL_MAX_10_EXP__ 4932
#define __LDBL_MAX_EXP__ 16384
#define __LDBL_MAX__ 1.18973149535723176502e+4932L
#define __LDBL_MIN_10_EXP__ (-4931)
#define __LDBL_MIN_EXP__ (-16381)
#define __LDBL_MIN__ 3.36210314311209350626e-4932L
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
#define __LONG_MAX__ 0x7fffffffffffffffL
#define __LP64__ 1
#define __MMX__ 1
#define __NO_INLINE__ 1
#define __ORDER_BIG_ENDIAN__ 4321
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __ORDER_PDP_ENDIAN__ 3412
#define __PIC__ 2
#define __PIE__ 2
#define __PRAGMA_REDEFINE_EXTNAME 1
#define __PTRDIFF_MAX__ 0x7fffffffffffffffL
#define __PTRDIFF_TYPE__ long int
#define __REGISTER_PREFIX__ 
#define __SCHAR_MAX__ 0x7f
#define __SEG_FS 1
#define __SEG_GS 1
#define __SHRT_MAX__ 0x7fff
#define __SIG_ATOMIC_MAX__ 0x7fffffff
#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
#define __SIG_ATOMIC_TYPE__ int
#define __SIZEOF_DOUBLE__ 8
#define __SIZEOF_FLOAT128__ 16
#define __SIZEOF_FLOAT80__ 16
#define __SIZEOF_FLOAT__ 4
#define __SIZEOF_INT128__ 16
#define __SIZEOF_INT__ 4
#define __SIZEOF_LONG_DOUBLE__ 16
#define __SIZEOF_LONG_LONG__ 8
#define __SIZEOF_LONG__ 8
#define __SIZEOF_POINTER__ 8
#define __SIZEOF_PTRDIFF_T__ 8
#define __SIZEOF_SHORT__ 2
#define __SIZEOF_SIZE_T__ 8
#define __SIZEOF_WCHAR_T__ 4
#define __SIZEOF_WINT_T__ 4
#define __SIZE_MAX__ 0xffffffffffffffffUL
#define __SIZE_TYPE__ long unsigned int
#define __SSE2_MATH__ 1
#define __SSE2__ 1
#define __SSE_MATH__ 1
#define __SSE__ 1
#define __SSP_STRONG__ 3
#define __STDC_HOSTED__ 1
#define __STDC_IEC_559_COMPLEX__ 1
#define __STDC_IEC_559__ 1
#define __STDC_ISO_10646__ 201605L
#define __STDC_NO_THREADS__ 1
#define __STDC_UTF_16__ 1
#define __STDC_UTF_32__ 1
#define __STDC_VERSION__ 201112L
#define __STDC__ 1
#define __UINT16_C(c) c
#define __UINT16_MAX__ 0xffff
#define __UINT16_TYPE__ short unsigned int
#define __UINT32_C(c) c ## U
#define __UINT32_MAX__ 0xffffffffU
#define __UINT32_TYPE__ unsigned int
#define __UINT64_C(c) c ## UL
#define __UINT64_MAX__ 0xffffffffffffffffUL
#define __UINT64_TYPE__ long unsigned int
#define __UINT8_C(c) c
#define __UINT8_MAX__ 0xff
#define __UINT8_TYPE__ unsigned char
#define __UINTMAX_C(c) c ## UL
#define __UINTMAX_MAX__ 0xffffffffffffffffUL
#define __UINTMAX_TYPE__ long unsigned int
#define __UINTPTR_MAX__ 0xffffffffffffffffUL
#define __UINTPTR_TYPE__ long unsigned int
#define __UINT_FAST16_MAX__ 0xffffffffffffffffUL
#define __UINT_FAST16_TYPE__ long unsigned int
#define __UINT_FAST32_MAX__ 0xffffffffffffffffUL
#define __UINT_FAST32_TYPE__ long unsigned int
#define __UINT_FAST64_MAX__ 0xffffffffffffffffUL
#define __UINT_FAST64_TYPE__ long unsigned int
#define __UINT_FAST8_MAX__ 0xff
#define __UINT_FAST8_TYPE__ unsigned char
#define __UINT_LEAST16_MAX__ 0xffff
#define __UINT_LEAST16_TYPE__ short unsigned int
#define __UINT_LEAST32_MAX__ 0xffffffffU
#define __UINT_LEAST32_TYPE__ unsigned int
#define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL
#define __UINT_LEAST64_TYPE__ long unsigned int
#define __UINT_LEAST8_MAX__ 0xff
#define __UINT_LEAST8_TYPE__ unsigned char
#define __USER_LABEL_PREFIX__ 
#define __VERSION__ "6.3.0 20170406"
#define __WCHAR_MAX__ 0x7fffffff
#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
#define __WCHAR_TYPE__ int
#define __WINT_MAX__ 0xffffffffU
#define __WINT_MIN__ 0U
#define __WINT_TYPE__ unsigned int
#define __amd64 1
#define __amd64__ 1
#define __code_model_small__ 1
#define __gnu_linux__ 1
#define __has_include(STR) __has_include__(STR)
#define __has_include_next(STR) __has_include_next__(STR)
#define __k8 1
#define __k8__ 1
#define __linux 1
#define __linux__ 1
#define __pic__ 2
#define __pie__ 2
#define __unix 1
#define __unix__ 1
#define __x86_64 1
#define __x86_64__ 1
#define linux 1
#define unix 1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.