2012-10-25 75 views
13

tôi (nhanh chóng) viết một số mã và vô tình đảo ngược các đối số trong scanf():luận Inverted trong scanf()

char i[] = "ABC1\t"; 
scanf(i, "%s"); 

Biên soạn với gcc -Werror -Wall -Wextra không phàn nàn về một chút này. Rõ ràng, mã này không hoạt động, nhưng tại sao gcc không thông báo cho tôi rằng tôi đã đảo ngược các đối số? Không thể phát hiện rằng i không phải là chuỗi định dạng hoặc đối số thứ hai không phải là loại có thể lưu trữ?

EDIT
Cảm ơn vì sự hiểu biết tất cả, Hình như tôi thấy câu trả lời, đã có một twist trên -Wformat cờ mà làm này "catchable" (được đăng dưới đây để tham khảo)

Trả lời

17

Ha! Tôi tìm thấy nó. Đánh gcc với cờ -Wformat=2 đã bắt được nó.

gửi bài các thông tin để tham khảo của người khác:

Đây là list of flags I found

-Wformat Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified...

tôi đã giả định -Wall-Wformat trong nó, mà nó, nhưng phần thực sự quan trọng về những gì tôi chỉ được tìm thấy:

-Wformat is included in -Wall. For more control over some aspects of format checking, the options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, and -Wformat=2 are available, but are not included in -Wall.

+0

Vâng, +1 Tôi cũng đang tìm kiếm nó. \ – Omkant

8

Tôi cho rằng nó không nên.

int scanf (const char * format, ...); 

i được bình thường chuyển đổi sang một const char*, tất cả các thông số còn lại chỉ là "tỉnh lược" và không thể kiểm tra tại thời gian biên dịch.

+1

Nặng Ders được sử dụng bởi GCC thường có tham số đầu tiên được đánh dấu là một chuỗi định dạng và sau đó nó có thể đảm bảo rằng các loại chính xác được chuyển đến các tham số còn lại, cung cấp '-Wformat' được cung cấp. Tôi tin rằng đây là một phần của '-Wall'. – Will

+1

@Will Nhưng sau đó một lần nữa - một non-const char * đã được thông qua như là một chuỗi định dạng (mà là hợp lệ của chính nó) và do đó trình biên dịch đã không lực lượng kiểm tra tham số. Nó có thể đã làm như vậy nếu chuỗi định dạng là 'const char *' hoặc chữ. – Lyth

+0

Có lẽ nó không kiểm tra giữa 'char * fmt' & 'const char * fmt'. Bất cứ ai có thể cho biết, nếu đối số thứ hai ("ABC \ t") sẽ là char * hoặc const char *? – anishsane

3

Các bài hướng dẫn về scanf (người đàn ông scanf) cung cấp cho các nguyên mẫu:

int scanf(const char *format, ...); 

Một char [] chỉ là một loại đặc biệt của char *, do đó số đầu tiên là hài lòng. Các đối số thứ cấp được đánh giá trong thời gian chạy (nếu tôi nhớ lại), vì vậy chúng không được trình biên dịch xem xét ở đây. Từ triển vọng của trình biên dịch, đây là một lời gọi tốt cho hàm được đưa ra nguyên mẫu của nó.

Ngoài ra, trình biên dịch không bao giờ kiểm tra xem bạn có đang cố ghi vào vị trí không hợp lệ hay không. Điều tuyệt vời (hoặc khủng khiếp) về C là nó sẽ cho phép bạn làm nhiều hơn hoặc ít hơn những gì bạn muốn, ngay cả khi những gì bạn muốn là một ý tưởng tồi.

+2

Đúng là 'scanf' tự chấp nhận chúng, nhưng trong glibc, được biên dịch bằng gcc, scanf có' __attribute __ ((định dạng (scanf, 1, 2))) 'cho trình biên dịch biết chắc các tham số là đúng, mặc dù điều này không được thực thi bởi việc khai báo 'scanf'. – Shahbaz