2009-03-31 12 views
5

Tôi vừa xem qua trang người đàn ông cho printf và có điều gì đó xảy ra với tôi. Tôi đã tự hỏi nếu có bất kỳ "luật sư ngôn ngữ" ở đây mà có thể trả lời một câu hỏi tương đối đơn giản: -P.câu hỏi về các thông số định dạng printf không tương thích

Vì vậy, 't' modifier được định nghĩa là

Chuyển đổi số nguyên sau tương ứng với một cuộc tranh luận ptrdiff_t.

Vì vậy, có nghĩa là gì xảy ra nếu bạn kết hợp điều này với một chuyển đổi nguyên không dấu? Rõ ràng là o, u, x và X tất cả đều được hiểu là giá trị chưa ký, trong khi d và i được ký.

Tương tự như vậy, có các phiên bản đã ký/chưa ký cho tất cả các công cụ sửa đổi (int/unsigned int, size_t/ssize_t, v.v.) trừ ptrdiff_t.

Trong thực tế, không có gì xấu xảy ra do các phiên bản loại chưa ký chiếm cùng một lượng không gian như các phiên bản đã ký. Vì vậy, quyền về byte được bật ra khỏi ngăn xếp.

Vì vậy, không có gì "xấu" xảy ra, trên thực tế, khi in ra giá trị kỳ vọng cho tất cả mọi thứ được kiểm tra ngoại trừ "INT_MIN" (giả định rằng sizeof(int) == sizeof(ptrdiff_t).

printf("%tu %td\n", INT_MIN, INT_MIN); 

in

2147483648 -2147483648 

trên Hệ thống 32 bit

Tiêu chuẩn có bất kỳ ý kiến ​​nào về điều này không? Tôi cho rằng câu trả lời sẽ là "hành vi không xác định". Nhưng tôi nghĩ tôi sẽ hỏi;).

+0

Điều này có bất cứ điều gì để làm với C + + (ít nhất là trước khi C + + 0x)? Là printf() vv sẽ được thay đổi trong C + + 0x để phù hợp với C99? Tôi nghĩ bạn nên gỡ bỏ thẻ C++. –

+0

ptrdiff_t được định nghĩa trong cstddef trong C++. printf rõ ràng tồn tại trong c + + là tốt. Tôi không biết C++ 0x thay đổi printf ở tất cả. –

+0

hrmm, có vẻ như C++ có thể không có bộ sửa đổi c99 't'. Đủ công bằng. –

Trả lời

3

Không có gì để xem ở đây. Mã bạn viết là hợp pháp.

Chỉ cần một số sự kiện là tại sao:

  • tất cả các loại nguyên ký có các đối tác unsigned, với các yêu cầu kích thước/liên kết cùng
  • ptrdiff_t được quy định là một loại nguyên chữ ký của tiêu chuẩn. Vì vậy, nó có một đôi chưa ký. (Trong thực tế, logic tương tự áp dụng cho size_t cũng - ssize_t không phải là C, nhưng POSIX)
  • các t dài specifier phải làm việc với d, i, o, u, x, X loại
+0

tương đương không hợp lệ tương đương với ptrdiff_t là gì? – user83255

+0

Nó không có tên đặc biệt - bạn chỉ có thể nói rằng nếu ptrdiff_t là "dài" thì đối tác chưa ký của nó là "unsigned long long" vv – jpalecek

+0

Thực tế quan trọng mà bạn bỏ qua là, trong trường hợp giá trị phù hợp với cả biến số đã ký và chưa ký của một kiểu số nguyên, nó có cùng biểu diễn, và tiêu chuẩn cho phép chuyển kiểu đối số "sai" trong trường hợp này (chỉ có thể có cho các hàm không có hàm nguyên mẫu và hàm variadic). Theo như tôi có thể nói, nó sẽ là UB để vượt qua một giá trị 'ptrdiff_t' âm khi định dạng specifier mong đợi một loại unsigned. –