2010-07-28 45 views
10

này đơn giản tập tin c:unistd.h và c99 trên Linux

#include <unistd.h> 

void test() { 
    char string[40]; 
    gethostname(string,40); 
} 

... khi biên dịch bình thường, hoạt động tốt:

$ cc -Wall -c -o tmp.o tmp.c 
$ 

... nhưng khi biên soạn trong chế độ C99, đưa ra cảnh báo:

$ cc -Wall -std=c99 -c -o tmp.o tmp.c 
tmp.c: In function `test': 
tmp.c:5: warning: implicit declaration of function `gethostname' 
$ 

Tệp kết quả .o là tốt và liên kết hoạt động. Tôi chỉ muốn thoát khỏi cảnh báo. Tôi có thể đạt được điều này một cách hacky, bằng cách đặt tờ khai trong tập tin .h của riêng tôi.

Điều gì về C99 có nghĩa là các khai báo trong unistd.h không được bao gồm? Điều này có thể khắc phục, mà không từ bỏ sự độc đáo của C99?

Tôi thấy cùng một vấn đề với các libs chuẩn khác.

Trả lời

15

Bạn có thể cần phải xác định một số macro trong một cách particluar để có được những nguyên mẫu cho gethostname()

Từ man gethostname:

Tính năng thử nghiệm Yêu cầu Macro cho glibc (xem feature_test_macros (7)):

gethostname(): _BSD_SOURCE || _XOPEN_SOURCE >= 500 
    sethostname(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500) 

Vì vậy:

#define _BSD_SOURCE 

#include <unistd.h> 

void test() { 
    char string[40]; 
    gethostname(string,40); 
} 

Các chi tiết đẫm máu:

Nếu bạn không chỉ định tùy chọn -std-c99, sau đó features.h (được ngầm bao gồm theo unistd.h) sẽ mặc định thiết lập _BSD_SOURCE theo cách như vậy mà nguyên mẫu cho gethostname() được bao gồm . Tuy nhiên, việc chỉ định -std=c99 làm cho trình biên dịch tự động xác định __STRICT_ANSI__, do đó gây ra features.h để không xác định _BSD_SOURCE, trừ khi bạn ép buộc với định nghĩa macro của đối tượng địa lý của riêng bạn (như trên).

+0

+1 Điều trị rất kỹ lưỡng. –

+1

+1 để có câu trả lời. -10 cho '#define _BSD_SOURCE'. Vui lòng sử dụng '#define _XOPEN_SOURCE 500' hoặc tốt hơn trong chuỗi xây dựng:' cc -D_XOPEN_SOURCE = 500 ... '. Vâng, rằng nếu bất kỳ loại di động là mong muốn. – Dummy00001

+0

Như với câu trả lời của tôi cho Luther - 'man gethostname' trên hệ thống Red Hat của tôi không đề cập đến các yêu cầu về tính năng Macro thử nghiệm. Bất cứ ai có bất kỳ ý tưởng tại sao? – slim

10

gethostname() không phải là hàm C chuẩn (không được đề cập ở bất kỳ đâu trong tiêu chuẩn C99), vì vậy biểu tượng không được xác định chính xác khi biên dịch theo tiêu chuẩn.

Nếu bạn đang sử dụng chuỗi công cụ gcc, hãy sử dụng -std=gnu99 và bạn sẽ nhận được hành vi bạn muốn.

Cách khác, xem <features.h>, có vẻ như bạn có thể sử dụng -D_GNU_SOURCE hoặc -D_XOPEN_SOURCE=500 để nhận được hành vi mong muốn.

+0

Mặc dù tôi đã chấp nhận một câu trả lời khác, '-std = gnu99' là bản sửa lỗi tôi thực sự đã sử dụng. Cảm ơn. – slim

+0

Chỉ cần chạy chính xác vấn đề này và chọn '-std = gnu99'. – Cubbi

4

Đọc man gethostname. Nó nói trong Yêu cầu tính năng thử nghiệm vĩ mô, rằng _BSD_SOURCE (hoặc _XOPEN_SOURCE>500) là bắt buộc để kéo gethostname từ unistd.h.

Đọc tiếp man feature_test_macros. Bạn sẽ thấy rằng -std=c99 bật trên __STRICT_ANSI__ trong đó tắt_BSD_SOURCE.Điều này có nghĩa là bạn không thể nhận được gethostname từ unistd.h trừ khi bạn xác định lại _BSD_SOURCE. Tôi thường đặt _GNU_SOURCE trên dòng lệnh của mình (ví dụ: gcc -D_GNU_SOURCE -std=c99 file.c) cho hầu hết mọi thứ, cũng bật trên số _BSD_SOURCE.

P.S. Trang hướng dẫn sử dụng chứa một chương trình ví dụ có thể in các ft-macro hiện tại. Bạn có thể biên dịch và chạy nó cho một số thiết lập trình biên dịch.

+0

Không ai trong số đó nằm trong 'man gethostname' trên hệ thống redhat của tôi. Hệ thống của bạn là gì? Tôi có nên cài đặt thêm manpages không? – slim