2012-07-03 32 views
9

Các chương trình sau đây đã không xác định:Tại sao gcc -Wformat không cảnh báo về printf% d trên int không dấu? hành vi

#include <stdio.h> 

int main(void) 
{ 
    unsigned int x = -100; // This is fine, becomes UINT_MAX - 100 
    printf("%d\n", x); // This is undefined behavior. 
    return 0; 
} 

C99 7.19.6.1p8 bang% d hy vọng một cuộc tranh cãi int.

C99 7.19.6.1p9 khẳng định: "Nếu bất kỳ tranh luận không phải là loại chính xác cho các tương ứng đặc điểm kỹ thuật chuyển đổi, hành vi này là không xác định ."

Tuy nhiên, gcc -Wformat (bao gồm -Wall) sẽ không khiếu nại về chương trình trên, tại sao? Đây có phải là lỗi hay thiếu sót có chủ ý không?

Từ manpage gcc:

-Wformat 

Kiểm tra các cuộc gọi đến và "printf""scanf", vv, để đảm bảo rằng các đối số cung cấp có các loại phù hợp với chuỗi định dạng xác định, và rằng các chuyển đổi theo quy định tại các định dạng string make sense

+2

C99 6.3.1.3p3 nói chuyển đổi unsigned để ký kết được thực hiện xác định. – jxh

+0

@ user315052: Không có chuyển đổi; biểu diễn của 'x' (một đối tượng' unsigned int') được hiểu như thể nó là kiểu 'int'. –

+0

@KeithThompson: Tôi nghĩ rằng đó là vì C99 7.15.1.1p2, câu cuối cùng, nơi nó làm cho một ngoại lệ cho đã ký/unsigned khi chuyển đổi các loại đối số thông qua vĩ mô 'va_arg'. – jxh

Trả lời

8

Đoán tốt nhất của tôi là cảnh báo bị bỏ qua vì UB được cho là được gọi bởi giá trị và không chỉ theo loại. va_arg cho phép ký kết không khớp với điều kiện giá trị được thể hiện trong cả loại đã ký và chưa ký. Tuy nhiên, printf và bạn bè không được chỉ định theo điều khoản của va_arg và các trạng thái tiêu chuẩn rằng bất kỳ loại không phù hợp kết quả trong UB, nhưng điều này có lẽ là một lỗi trong tiêu chuẩn. Nếu không, printf("%x",1); sẽ gọi UB. Xem câu hỏi của tôi về chủ đề này:

Does printf("%x",1) invoke undefined behavior?

+0

Cảm ơn. Điều đó có ý nghĩa khi 6.2.5p6 yêu cầu int và unsigned int để sử dụng cùng một lượng lưu trữ. Mặc dù printf% d trên một unsigned là về mặt kỹ thuật undefined, không có lý do chính đáng cho nó gây ra vấn đề thực sự. – Chris

+0

Tiêu chuẩn không nói rằng 'printf()' sử dụng '', nhưng thực tế bạn có thể xây dựng một con trỏ tới hàm 'printf()' có thể gọi thông qua nó hàm ý ít nhất một số tính phổ biến trong cơ chế chuyển đối số . –

+3

GCC 5.0 có cảnh báo như vậy bây giờ: ['-Wformat-signedness'] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60194) (được bật bởi' -Wformat'). – cremno

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