Đây là mã của tôi:
#include <string.h>
#include <stdio.h>
typedef char BUF[8];
typedef struct
{
BUF b[23];
} S;
S s;
int main()
{
int n;
memcpy(&s, "1234567812345678", 17);
n = strlen((char *)&s.b) / sizeof(BUF);
printf("%d\n", n);
n = strlen((char *)&s) / sizeof(BUF);
printf("%d\n", n);
}
Sử dụng gcc 8.3.0 hoặc 8.2.1 với bất kỳ mức tối ưu hóa nào ngoại trừ -O0
, điều này xuất ra 0 2
khi tôi đang mong đợi2 2
. Trình biên dịch đã quyết định rằng strlen
giới hạn b[0]
và do đó không bao giờ có thể bằng hoặc vượt quá giá trị được chia cho.
Đây có phải là một lỗi trong mã của tôi hoặc một lỗi trong trình biên dịch?
Điều này không được nêu rõ trong tiêu chuẩn, nhưng tôi nghĩ cách giải thích chính của xuất xứ con trỏ là đối với bất kỳ đối tượng nào X
, mã (char *)&X
sẽ tạo ra một con trỏ có thể lặp lại trên toàn bộ X
- khái niệm này sẽ giữ ngay cả khi X
có mảng phụ như cấu trúc bên trong.
(Câu hỏi thưởng, có cờ gcc để tắt tối ưu hóa cụ thể này không?)
2 2
dưới nhiều tùy chọn khác nhau.
s.b
bị giới b[0]
hạn ở 8 ký tự và do đó có hai tùy chọn: (1) truy cập ngoài giới hạn trong trường hợp có 8 ký tự không null, đó là UB, (2) có một ký tự null, trong đó len nhỏ hơn 8, do đó chia cho 8 cho không. Vì vậy, kết hợp trình biên dịch (1) + (2) có thể sử dụng UB để đưa ra kết quả giống nhau cho cả hai trường hợp