Những gì #define _GNU_SOURCE 'ngụ ý gì?


152

Hôm nay tôi phải sử dụng basename()chức năng này và man 3 basename( ở đây ) đã cho tôi một số tin nhắn lạ:

Ghi chú

Có hai phiên bản khác nhau của basename () - phiên bản POSIX được mô tả ở trên và phiên bản GNU , phiên bản nào có sau

#define _GNU_SOURCE
#include <string.h>

Tôi đang tự hỏi điều này #define _GNU_SOURCEcó nghĩa là gì: nó có làm mờ mã tôi viết bằng giấy phép liên quan đến GNU không? Hoặc đơn giản là nó được sử dụng để nói với trình biên dịch một cái gì đó như " Chà, tôi biết, bộ chức năng này không phải là POSIX, do đó không thể mang theo được, nhưng dù sao tôi cũng muốn sử dụng nó ".

Nếu vậy, tại sao không cung cấp cho mọi người các tiêu đề khác nhau, thay vì phải xác định một số macro tối nghĩa để thực hiện một chức năng này hay chức năng khác?

Một cái gì đó cũng lỗi tôi: làm thế nào trình biên dịch biết thực hiện chức năng nào để liên kết với thực thi? Liệu nó có sử dụng điều này #definelà tốt?

Bất cứ ai có một số gợi ý để cung cấp cho tôi?

Câu trả lời:


172

Xác định _GNU_SOURCEkhông liên quan gì đến giấy phép và mọi thứ liên quan đến việc viết mã (không phải) mã di động. Nếu bạn xác định _GNU_SOURCE, bạn sẽ nhận được:

  1. truy cập vào nhiều hàm mở rộng GNU / Linux không chuẩn
  2. truy cập vào các chức năng truyền thống đã bị bỏ qua từ tiêu chuẩn POSIX (thường vì lý do chính đáng, chẳng hạn như được thay thế bằng các lựa chọn thay thế tốt hơn hoặc được gắn với các triển khai di sản cụ thể)
  3. truy cập vào các chức năng ở mức độ thấp mà không thể được cầm tay, nhưng mà bạn đôi khi cần phải thực hiện các tiện ích hệ thống thích mount, ifconfigvv
  4. hành vi bị hỏng đối với nhiều hàm do POSIX chỉ định, trong đó người GNU không đồng ý với ủy ban tiêu chuẩn về cách các hàm nên hành xử và quyết định làm việc của riêng họ.

Miễn là bạn nhận thức được những điều này, đó không phải là vấn đề cần xác định _GNU_SOURCE, nhưng bạn nên tránh xác định nó và thay vào đó hãy xác định _POSIX_C_SOURCE=200809Lhoặc _XOPEN_SOURCE=700khi có thể để đảm bảo rằng các chương trình của bạn có thể mang theo được.

Cụ thể, những thứ _GNU_SOURCEmà bạn không bao giờ nên sử dụng là # 2 và # 4 ở trên.


71
Tất nhiên, mọi người đều biết lý do thực sự để xác định _GNU_SOURCElà để có được strfrymemfrob.
dùng4815162342

5
Liên kết này đến tài liệu Thư viện GNU C cung cấp một số chi tiết bổ sung (ví dụ: #define _GNU_SOURCEđược khuyến nghị là "điều đầu tiên trong tệp, chỉ trước các bình luận").
Alexander Pozdneev

Không liên quan nhưng được sử dụng để mở rộng giới hạn kích thước tệp 2GB trên các mục tiêu 32 bit.
mckenzm

1
@mckenzm: Tôi nghĩ bạn đang nghĩ đến _FILE_OFFSET_BITS, không phải _GNU_SOURCE.
R .. GitHub DỪNG GIÚP ICE

Tôi muốn trở thành một lập trình viên trả phí cho việc chuyển các memfrob strfry và các tiện ích tương tự với các nền tảng và chuỗi công cụ khác.
Massimo

6

Hãy để tôi trả lời hai điểm nữa:

Một cái gì đó cũng lỗi tôi: làm thế nào trình biên dịch biết thực hiện chức năng nào để liên kết với thực thi? Nó có sử dụng #define này không?

Một cách tiếp cận phổ biến là #defineđịnh danh có điều kiện basenamecho các tên khác nhau, tùy thuộc vào việc _GNU_SOURCEđược xác định. Ví dụ:

#ifdef _GNU_SOURCE
# define basename __basename_gnu
#else
# define basename __basename_nongnu
#endif

Bây giờ thư viện chỉ cần cung cấp cả hai hành vi dưới những tên đó.

Nếu vậy, tại sao không cung cấp cho mọi người các tiêu đề khác nhau, thay vì phải xác định một số biến môi trường tối nghĩa để thực hiện một chức năng này hay chức năng khác?

Thông thường, cùng một tiêu đề có nội dung hơi khác nhau trong các phiên bản Unix khác nhau, do đó, không có nội dung đúng duy nhất cho <string.h>- có nhiều tiêu chuẩn ( xkcd ). Có cả bộ macro để chọn một macro yêu thích của bạn, để nếu chương trình của bạn mong đợi một tiêu chuẩn, thư viện sẽ tuân theo điều đó.


6

Để biết chi tiết chính xác về tất cả những gì được kích hoạt bởi _GNU_SOURCE, tài liệu có thể giúp đỡ.

Từ tài liệu GNU:

Macro: _GNU_SOURCE

Nếu bạn xác định macro này, mọi thứ đều được bao gồm: các phần mở rộng ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X / Open, LFS và GNU. Trong trường hợp POSIX.1 xung đột với BSD, các định nghĩa POSIX được ưu tiên.

Từ trang Linux cho các macro kiểm tra tính năng :

_GNU_SOURCE

Xác định macro này (với bất kỳ giá trị nào) định nghĩa ngầm định _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_SOURCE _XOPEN_SOURCE với giá trị 700 (600 trong các phiên bản glibc trước 2.10; 500 trong các phiên bản glibc trước 2.2). Ngoài ra, các phần mở rộng dành riêng cho GNU cũng được hiển thị.

Kể từ glibc 2.19, việc xác định _GNU_SOURCE cũng có tác dụng xác định ngầm định _DEFAULT_SOURCE. Trong các phiên bản glibc trước 2.20, việc xác định _GNU_SOURCE cũng có tác dụng xác định ngầm định _BSD_SOURCE và _SVID_SOURCE.

Lưu ý : _GNU_SOURCEcần được xác định trước khi bao gồm các tệp tiêu đề để các tiêu đề tương ứng kích hoạt các tính năng. Ví dụ:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
...

_GNU_SOURCEcũng có thể được kích hoạt trên mỗi phần biên dịch bằng -Dcờ:

$ gcc -D_GNU_SOURCE file.c

( -Dkhông cụ thể _GNU_SOURCEnhưng bất kỳ macro nào được định nghĩa theo cách này).


4

Từ một số danh sách gửi thư qua google:

Nhìn vào bao gồm / tính năng của glibc: h:

_GNU_SOURCE Tất cả các mục trên, cộng với các phần mở rộng GNU.

Có nghĩa là nó cho phép tất cả điều này:

STRICT_ANSI , _ISOC99_SOURCE, _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED, _LARGEFILE_SOURCE, _LARGEFILE64_SOURCE, _FILE_OFFSET_BITS = N, _BSD_SOURCE, _SVID_SOURCE

Vì vậy, nó cho phép rất nhiều cờ biên dịch cho gcc


21
Nó không ảnh hưởng đến hành vi của trình biên dịch, chỉ những gì nguyên mẫu và những thứ có thể nhìn thấy từ các tiêu đề.
Spudd86
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.