Hãy thử 285212672ULL
; nếu bạn viết nó mà không có hậu tố, bạn sẽ thấy trình biên dịch xử lý nó như một số nguyên thông thường. Lý do nó làm việc trong một biến là bởi vì số nguyên đang được đúc lên đến một unsigned long long
trong nhiệm vụ, để giá trị được chuyển đến printf()
là đúng loại.
Và trước khi bạn hỏi, không, trình biên dịch có thể không phải là đủ thông minh để hình dung nó ra từ "%llu
"trong chuỗi định dạng printf()
. Đó là một mức độ trừu tượng khác nhau. Trình biên dịch chịu trách nhiệm về cú pháp ngôn ngữ , printf()
ngữ nghĩa không phải là một phần của cú pháp, đó là một chức năng thư viện runtime (không khác gì thực sự từ chức năng của riêng bạn ngoại trừ việc nó được bao gồm trong tiêu chuẩn).
Xét đoạn mã sau cho một int 32-bit và 64 -bit hệ thống dài không có ký hiệu:
#include <stdio.h>
int main (void) {
printf ("%llu\n",1,2);
printf ("%llu\n",1ULL,2);
return 0;
}
mà kết quả đầu ra:
8589934593
1
Trong trường hợp đầu tiên, hai 32-bit số nguyên 1 và 2 được đẩy vào stack và printf()
giải thích rằng khi một giá trị duy nhất 64-bit ULL, 2 x 2 + 1. Đối số 2
đang được vô tình bao gồm trong giá trị ULL.
Trong giây, bạn thực sự đẩy giá trị 1 bit 64 bit và số nguyên 32 bit thừa 2
, bị bỏ qua.
Lưu ý rằng điều này "thoát khỏi bước" giữa chuỗi định dạng của bạn và đối số thực tế của bạn là một ý tưởng tồi. Một cái gì đó như:
printf ("%llu %s %d\n", 0, "hello", 0);
có thể sụp đổ vì 32-bit "hello"
con trỏ sẽ được tiêu thụ bởi các %llu
và %s
sẽ cố gắng bỏ tham khảo trận chung kết 0
tranh cãi. "Hình ảnh" sau đây minh họa điều này (giả sử rằng các ô là 32 bit và chuỗi "hello" được lưu trữ ở 0xbf000000.
What you pass Stack frames What printf() uses
+------------+
0 | 0 | \
+------------+ > 64-bit value for %llu.
"hello" | 0xbf000000 |/
+------------+
0 | 0 | value for %s (likely core dump here).
+------------+
| ? | value for %d (could be anything).
+------------+
nhưng tôi nghĩ rằng trình biên dịch là đủ thông minh để tìm ra% u trong printf định dạng spec, hãy thử printf ("% d% u", ~ 0, ~ 0) .. cả hai sẽ in các giá trị như mong đợi .. – sud03r
Không - những kiểu dữ liệu có cùng kích thước - đó là printf() tìm ra - thử % d với 'a'. – paxdiablo
Pax: Điều đó cũng tốt, các ký tự chữ cái là hằng số nguyên. – caf