C không và chưa bao giờ có loại chuỗi gốc. Theo quy ước, ngôn ngữ sử dụng các mảng char
chấm dứt bằng một ký tự null, nghĩa là, với '\0'
. Các hàm và macro trong các thư viện chuẩn của ngôn ngữ cung cấp hỗ trợ cho các mảng ký tự null kết thúc, ví dụ: strlen lặp qua một mảng char
cho đến khi nó gặp một ký tự '\0'
và strcpy bản sao từ chuỗi nguồn cho đến khi gặp số '\0'
.
Việc sử dụng các chuỗi bị hủy trong C phản ánh thực tế rằng C được dự định chỉ cao hơn một chút so với ngôn ngữ lắp ráp. Các chuỗi không được chấm dứt đã được hỗ trợ trực tiếp tại thời điểm đó trong assembly language for the PDP-10 and PDP-11.
Điều đáng lưu ý là thuộc tính này của chuỗi C dẫn đến khá nhiều lỗi tràn bộ đệm khó chịu, bao gồm cả lỗi bảo mật nghiêm trọng. Ví dụ, nếu bạn quên null-chấm dứt chuỗi ký tự được chuyển như đối số nguồn thành strcpy
, hàm sẽ tiếp tục sao chép các byte tuần tự từ bất kỳ điều gì xảy ra trong bộ nhớ trong quá trình kết thúc chuỗi nguồn cho đến khi nó xảy ra khi gặp phải 0
, có khả năng ghi đè bất kỳ thông tin có giá trị nào sau vị trí của chuỗi đích trong bộ nhớ.
Trong ví dụ mã của bạn, chuỗi chữ "Hello, world!" sẽ được biên dịch thành mảng dài 14 byte của char
. 13 byte đầu tiên sẽ giữ các chữ cái, dấu phẩy, dấu cách và dấu chấm than và byte cuối cùng sẽ giữ ký tự null-terminator '\0'
, được trình biên dịch thêm tự động cho bạn. Nếu bạn truy cập phần tử cuối cùng của mảng, bạn sẽ tìm thấy nó bằng 0
. Ví dụ:
const char foo[] = "Hello, world!";
assert(foo[12] == '!');
assert(foo[13] == '\0');
Tuy nhiên, trong ví dụ của bạn, message
chỉ dài 10 byte. strcpy
sẽ viết tất cả 14 byte, bao gồm null-terminator, vào bộ nhớ bắt đầu tại địa chỉ của message
. 10 byte đầu tiên sẽ được ghi vào bộ nhớ được cấp phát trên ngăn xếp cho message
và bốn byte còn lại sẽ được ghi vào cuối ngăn xếp. Hệ quả của việc viết bốn byte thừa đó lên stack là khó dự đoán trong trường hợp này (trong ví dụ đơn giản này, nó có thể không làm hại gì), nhưng trong mã thực tế, nó thường dẫn đến lỗi dữ liệu hoặc lỗi truy cập bộ nhớ.
C không có chuỗi. – sashoalm
bạn cần thông báo char [14]; – acraig5075
Strcpy của bạn sẽ tràn mảng char của bạn bằng cách này. bạn cần ít nhất một mảng char có chiều dài 14 (13 ký tự + đầu cuối nul) – wich