2015-09-23 20 views
6

Sử dụng gcc 5.2.0, tôi nhận thấy rằng mã này không tạo ra một cảnh báo:Không cảnh báo khi trở về NULL với gcc

#include <stddef.h> 

int function(void) 
{ 
    return NULL; 
} 

void procedure(void) 
{ 
    return NULL; 
} 

tôi đã sử dụng lá cờ -Wall -Wextra -std=c99 -pedantic và tôi chạy archlinux. Tôi không chắc chắn tại sao mã này hoạt động tốt trên gcc, đặc biệt là từ clang 3.7.0 không tạo ra cảnh báo.

Tôi cũng đã thử với các phiên bản cũ hơn gcc như 4.9 hoặc 4.7 và cả hai đều tạo cảnh báo.

Những cảnh báo là:

warning: return makes integer from pointer without a cast 

warning: ‘return’ with a value, in function returning void 

tôi nên đề cập đến mà tôi cố gắng biên soạn gcc 5.2 trên Debian và kết quả là như nhau. Vì vậy, archlinux dường như không phải là vấn đề.

Lý do cơ bản là gì? Tôi dường như không thể tìm thấy bất cứ điều gì liên quan đến điều này bất cứ nơi nào khác.

Cảm ơn bạn!

+1

có thể trùng lặp http://stackoverflow.com/questions/1610030/why-can-you-return-from-a-non-void-function-without-returning-a-value-without-pr –

+0

Ý bạn là "đảo ngược trùng lặp"? Câu hỏi này hỏi tại sao bạn có thể trả về một giá trị trong phần thân của hàm void. Các "trùng lặp" hỏi tại sao bạn có thể viết một cơ thể của một chức năng không void mà không có một tuyên bố trở lại. – BitTickler

+0

có thể trùng lặp của [Tại sao không trả về 0x80000000 từ một hàm trả về int32 \ _t gây ra cảnh báo?] (Http://stackoverflow.com/questions/32656460/why-doesnt-returning-0x80000000-from-a-function -that-returns-int32-t-gây-a-wa) –

Trả lời

1

Tính hợp lệ của hàm đầu tiên phụ thuộc vào cách NULL được xác định. Không có vấn đề với chức năng đầu tiên nếu NULL được định nghĩa là 0. Nhưng nếu nó xảy ra được định nghĩa là (void *) 0 (thường là trường hợp trong mã C) thì hàm đầu tiên sẽ không hợp lệ. GCC thường rất dễ chấp nhận về các chuyển đổi từ con trỏ đến số nguyên tiềm ẩn.

Hàm thứ hai là không hợp lệ. Đặc tả ngôn ngữ nêu rõ rằng "Một câu lệnh trả về với một biểu thức sẽ không xuất hiện trong một hàm có kiểu trả về bị vô hiệu." Nếu nó biên dịch, nó phải là một ví dụ khác của GCC là quá chấp nhận về một cái gì đó.

Bạn cần chạy GCC ở chế độ -pedantic nếu bạn muốn đầu ra chẩn đoán của nó có liên quan đến ngôn ngữ C chuẩn. Trong chế độ mặc định nó không phải là một trình biên dịch C đáng tin cậy (ít nhất là trong therms đầu ra chẩn đoán của nó) và thực tế là nó "không đưa ra cảnh báo" có nghĩa là hoàn toàn không có gì.

Tuy nhiên, trong các thử nghiệm của mình, tôi không thể khiến GCC phàn nàn về chức năng thứ hai ngay cả với các công tắc -std=-pedantic. Nó trông giống như một lỗi trong trình biên dịch.

+0

OP tuyên bố sử dụng '-pantic'. – juanchopanza

+0

Tôi thực sự đang sử dụng '-pantic'. – damwdan

3

Điều này dường như là hồi quy trong gcc 5.2.0 - và, theo như tôi có thể nói, một điều kỳ lạ.

Với gcc 4.4.5 và 4.8.4, chương trình (sau khi thêm yêu cầu #include <stddef.h>) tạo cảnh báo trên cả hai câu hỏi return NULL;, ngay cả khi không có bất kỳ tùy chọn dòng lệnh bổ sung nào.

Với gcc 5.2.0, không có cảnh báo nào được tạo, ngay cả với gcc -c -Wall -Wextra -std=c99 -pedantic. Đối với cái thứ hai, trả về một giá trị từ một hàm void, một chẩn đoán là bắt buộc.

Bây giờ, đây là phần lạ.

$ gcc --version | head -n 1 
gcc (GCC) 5.2.0 
$ cat c.c 
#include <stddef.h> 

int function(void) { 
#ifdef USE_NULL 
    return NULL; 
#else 
    return ((void*)0); 
#endif 
} 

void procedure(void) { 
#ifdef USE_NULL 
    return NULL; 
#else 
    return ((void*)0); 
#endif 
} 
$ gcc -c c.c 
c.c: In function ‘function’: 
c.c:7:12: warning: return makes integer from pointer without a cast [-Wint-conversion] 
    return ((void*)0); 
      ^
c.c: In function ‘procedure’: 
c.c:15:12: warning: ‘return’ with a value, in function returning void 
    return ((void*)0); 
      ^
$ gcc -c -DUSE_NULL c.c 
$ 

Khi USE_NULL được xác định, không có cảnh báo nào được tạo.Biên dịch với gcc -E -DUSE_NULL (trong đó in đầu ra của bộ tiền xử lý để stdout) xác nhận rằng NULL được định nghĩa là ((void*)0). Nhưng khi tôi thay thế NULL bằng ((void*)0), các cảnh báo được tạo ra (như chúng phải là).

Tôi không biết chuyện gì đang diễn ra. Khi macro NULL đã được mở rộng, nó sẽ không thể phân biệt được từ ((void*)0), và hành vi của trình biên dịch thay đổi tùy thuộc vào việc được sử dụng.

+0

Bạn có thể có nghĩa là 5.2.0. –

+0

@AntoinePietri: Đã sửa lỗi! –

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