Sizeof xem loại biểu thức được cung cấp cho nó, nó không đánh giá biểu thức. Vì vậy, bạn chỉ cần đảm bảo rằng các biến được sử dụng trong biểu thức được khai báo để trình biên dịch có thể suy ra loại của chúng.
Trong ví dụ của bạn, st đã được khai báo là pointer-to-struct-retValue. Do đó trình biên dịch có thể suy ra loại biểu thức "* st".
Mặc dù nó không giống như nó đã được khai báo trong mã của bạn, trình biên dịch đã xử lý nó cho bạn. Tất cả các khai báo trong mã của bạn được chuyển đến đầu khối mà chúng xuất hiện bởi trình biên dịch. Giả sử bạn viết
Một cách để minh họa kiến thức có sẵn cho trình biên dịch là xem xét đầu ra trung gian mà nó tạo ra. Hãy xem xét ví dụ mã này ...
struct retValue {long int a, long int b};
...
printf("Hello World!\n");
struct retValue* st = malloc(sizeof(*st));
Sử dụng gcc là một ví dụ và teh mã trên trong main() chức năng của test.c, chúng ta hãy nhìn vào sản lượng trung gian bằng cách chạy ...
gcc -fdump-tree-cfg test.c
Trình biên dịch sẽ tạo ra các tập tin test.c.022t.cfg - Hãy nhìn vào nó và bạn sẽ thấy
[ ... removed internal stuff ...]
;; Function main (main)
Merging blocks 2 and 3
main (argc, argv)
{
struct retValue * st;
int D.3097;
void * D.3096;
# BLOCK 2
# PRED: ENTRY (fallthru)
__builtin_puts (&"Hello World!"[0]);
D.3096 = malloc (16);
st = (struct retValue *) D.3096;
D.3097 = 0;
return D.3097;
# SUCC: EXIT
}
Lưu ý cách khai báo được di chuyển đến đầu khối và đối số cho malloc đã được thay thế bằng giá trị thực tế biểu thị kích thước của loại biểu thức được đánh giá. Như đã chỉ ra trong các bình luận, thực tế là việc khai báo đã được chuyển lên đầu khối là một chi tiết thực hiện của trình biên dịch. Tuy nhiên, thực tế là trình biên dịch có thể làm điều này và cũng để chèn kích thước chính xác vào malloc tất cả cho thấy rằng trình biên dịch đã có thể suy ra các thông tin cần thiết từ đầu vào.
Cá nhân tôi thích đặt tên loại thực tế làm tham số cho sizeof, nhưng đó có thể là câu hỏi về kiểu mã hóa, nơi tôi muốn nói rằng tính nhất quán cao hơn sở thích cá nhân.
Bạn đã trả lời câu hỏi của riêng mình. sizeof (struct retValue) là chính xác –
Xin lỗi, câu hỏi không phải là 'Điều này đúng hay chính xác là gì?' đó là 'Tại sao nó hoạt động?' – Blackbinary
Nó có thể giúp hiểu nếu bạn thay đổi thuật ngữ. Bạn không * định nghĩa * một cấu trúc bằng cách sử dụng malloc, bạn đang * phân bổ * một cấu trúc bằng cách sử dụng malloc. Bạn đang định nghĩa 'st', là một con trỏ (không phải là một cấu trúc). Con trỏ đó đã được định nghĩa và có sẵn để sử dụng trong biểu thức khởi tạo (trên RHS của dấu bằng), nó chỉ không có giá trị, vì vậy hầu hết các sử dụng sẽ không hợp lệ. Điều này là OK, tuy nhiên, vì sizeof không sử dụng giá trị. –