2010-07-21 42 views
9

Tại sao trình biên dịch ANSI C không gắn cờ việc sử dụng đối số chuỗi ký tự trong một cuộc gọi hàm trong đó tham số correponding không có bộ định dạng const? Ví dụ, đoạn mã sau có thể tạo ra một ngoại lệ bằng cách cố gắng ghi vào bộ nhớ chỉ đọc.Chuỗi ký tự so với const char * trong C

void somefunc(char buffer[10]); 

void somefunc(char buffer[10]) { 
    int i; 

    for (i = 0; i < 10; i++) 
     buffer[i] = 0; 
} 

int main(int argc, char **argv) { 

    somefunc("Literal"); 
    return 0; 
} 

Tình trạng này có thể được xác định tại thời điểm biên dịch nhưng VS2010 và gcc không có vẻ như vậy. Gọi somefunc với một đối số const char * sẽ tạo ra một cảnh báo trình biên dịch.

+0

Câu hỏi hay - gcc không bắt được điều này, ngay cả với '-Wextra'. –

+0

Điểm tuyên bố một hàm là gì, sau đó xác định nó là dòng tiếp theo? :) – GManNickG

+0

Hans: Tôi đã sửa đổi câu hỏi để chỉ định ANSI C. Dù sao, tôi đã không đề xuất một lỗi trình biên dịch được ban hành. Cảnh báo cấp độ 3 hoặc 4 sẽ chỉ làm nổi bật một tình huống nguy hiểm tiềm tàng. – Robin

Trả lời

11

gcc: Sử dụng cờ -Wwrite-strings

PS. Hướng dẫn sử dụng gcc giải thích tại sao đây không phải là một phần của -Wall. Dù sao, như mọi khi, bạn nên tìm một sự kết hợp của -W cờ phù hợp với nhu cầu cụ thể của bạn và phong cách mã hóa. Ví dụ, trong một dự án gần đây tôi đã sử dụng một cái gì đó như thế này: -Werror -Wall -Wextra -Wformat=2 -Winit-self -Wswitch-enum -Wstrict-aliasing=2 -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wdisabled-optimization -Wunused-macros -Wno-unused

6

chuỗi ký tự không nằm trong C; trong C++.

chỉnh sửa: để xóa mọi nhầm lẫn về nhận xét của tôi, tôi đang đề cập đến loại, chứ không phải khả năng thực sự thay đổi chúng.

+1

Điều gì khiến bạn nghĩ vậy? –

+2

@Paul, anh ấy đúng. C99 §6.4.5/5: "Đối với các chuỗi ký tự chuỗi ký tự, các phần tử mảng có kiểu' char' "Nó không được xác định để sửa đổi một chuỗi ký tự, nhưng kiểu phần tử là' char', không phải 'const char'. –

+0

@Matthew: cảm ơn vì đã giải thích - tôi đã giải thích "const" có nghĩa là "chỉ đọc" (tất nhiên là các chuỗi ký tự thường là C hoặc C++) nhưng tôi hiểu ý nghĩa của bạn về * loại * thực tế của chuỗi chữ bây giờ. –

15

Đây là di sản K & R. Sửa chữa nó sẽ phá vỡ một triệu chương trình.

7

Điều Hans Passant nói. const đã được thêm vào như là một phần của tiêu chuẩn ANSI vào năm 1989, vì vậy bất cứ điều gì từ trước đó không có const.

+1

@Georg: Ý tôi là từ khóa const đã được thêm vào trong ANSI C, do đó, đã quá muộn để trang bị thêm các chuỗi ký tự với constness. – ninjalj

+0

Ah, bây giờ tôi có được bạn :) –

4

Trình biên dịch GNU (và trình biên dịch Intel C là tốt, iirc) sẽ phát ra một cảnh báo, nếu -Wwrite-string được sử dụng:

$ gcc -Wall -Wwrite-strings -o foo /tmp/foo.c 
/tmp/foo.c: In function 'main': 
/tmp/foo.c:12: warning: passing argument 1 of 'somefunc' discards qualifiers from pointer target type 
/tmp/foo.c:3: note: expected 'char *' but argument is of type 'const char *' 

Liên quan đến VS2010, tôi không thể giúp bạn.

+1

Cool - Tôi tự hỏi tại sao '-Wwrite-strings' không được bao gồm trong' -Wall' hoặc thậm chí '-Wextra' mặc dù? –

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