Tôi đang trải qua một sự đột biến quan tâm đến hệ thống loại biến đổi của C99. Câu hỏi này được lấy cảm hứng từ this one.Khả năng tương thích các loại được sửa đổi khác nhau và các tác động an ninh của nó
Kiểm tra mã từ câu hỏi này, tôi đã khám phá điều gì đó thú vị. Hãy xem xét mã này:
int myFunc(int, int, int, int[][100]);
int myFunc(int a, int b, int c, int d[][200]) {
/* Some code here... */
}
Điều này rõ ràng sẽ không (và không) biên dịch. Tuy nhiên, mã này:
int myFunc(int, int, int, int[][100]);
int myFunc(int a, int b, int c, int d[][c]) {
/* Some code here... */
}
biên dịch thậm chí không có cảnh báo (trên gcc).
Điều đó dường như ngụ ý rằng một loại mảng biến đổi có thể thay đổi tương thích với bất kỳ loại mảng không thay đổi nào khác!
Nhưng đó không phải là tất cả. Bạn sẽ mong đợi một loại biến đổi có thể thay đổi ít nhất là bận tâm với biến nào được sử dụng để thiết lập kích thước của nó. Nhưng nó không có vẻ như vậy!
int myFunc(int, int b, int, int[][b]);
int myFunc(int a, int b, int c, int d[][c]) {
return 0;
}
Cũng biên dịch mà không có bất kỳ lỗi nào.
Vì vậy, câu hỏi của tôi là: hành vi chuẩn hóa này có chính xác không?
Ngoài ra, nếu loại mảng biến đổi có thể thực sự tương thích với bất kỳ mảng nào có cùng kích thước, điều này có nghĩa là vấn đề bảo mật khó chịu không? Ví dụ: hãy xem xét mã sau:
int myFunc(int a, int b, int c, int d[][c]) {
printf("%d\n", sizeof(*d)/sizeof((*d)[0]));
return 0;
}
int main(){
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
myFunc(0, 0, 100, &arr);
return 0;
}
Biên dịch và kết quả đầu ra 100, không có lỗi hoặc cảnh báo, không có gì. Như tôi thấy, điều đó có nghĩa là mảng ngoài phạm vi dễ dàng viết ngay cả khi bạn đang kiểm tra nghiêm ngặt kích thước mảng của mình qua sizeof
, không thực hiện một dàn diễn viên và thậm chí có tất cả cảnh báo được bật! Hay tôi đang thiếu một cái gì đó?
Nếu bạn chưa làm như vậy, hãy thử thêm -std = c99-sai số-lỗi vào dòng biên dịch gcc của bạn và xem điều đó có tạo nên sự khác biệt nào không. – jschultz410
@ jschultz410: ý tưởng hay, nhưng không có sự khác biệt nào = ( – Mints97
Có nhiều trường hợp không thể cho trình biên dịch suy luận tĩnh giá trị của c (ví dụ - c là đầu vào từ stdin). nó thường không thể thực hiện bất kỳ loại kiểm tra tĩnh nào có ý nghĩa trên các tham số của định nghĩa hàm như vậy. Có vẻ như nếu bạn làm điều này, thì trình biên dịch sẽ nói "OK, tôi sẽ cho phép bạn chuyển bất cứ thứ gì bạn muốn làm d, " – jschultz410