2011-10-11 30 views

Trả lời

19

Trong hầu hết các trường hợp (ít nhất là trong C), bạn sẽ thấy rằng sizeof(*x) thực sự không đánh giá được *x. Các tiêu chuẩn C99 đã này nói trong 6.5.3.4 The sizeof operator, phần /2 (bolding của tôi):

Nhà điều hành sizeof mang lại kích thước (tính theo byte) của toán hạng của nó, có thể là một biểu thức hoặc tên trong ngoặc của một loại. Kích thước được xác định từ loại của toán hạng. Kết quả là một số nguyên. Nếu loại toán hạng là một loại mảng có độ dài biến đổi, toán hạng được đánh giá; nếu không, toán hạng không được đánh giá và kết quả là hằng số nguyên.

Vì vậy, đối với tất cả các VLA không phải là không có hội nghị diễn ra. Nếu loại *x VLA, được coi là một giai đoạn thực thi sizeof, một thứ cần phải được giải quyết khi mã đang chạy - tất cả những thứ khác có thể được tính toán tại thời gian biên dịch.

C++ có quy tắc hơi khác nhau, như thể hiện trong 5.3.3. Sizeof, phần /1:

Nhà điều hành sizeof mang lại số byte trong đại diện đối tượng của toán hạng của nó. Toán hạng là một biểu thức, là một toán hạng chưa được đánh giá (Điều 5), hoặc một kiểu id được mã hóa.

5. Expressions định nghĩa thuật ngữ "unevaluated toán hạng" trong phần /8:

Trong một số hoàn cảnh, toán hạng unevaluated xuất hiện. Toán hạng chưa được đánh giá không được đánh giá.

(có lẽ một trong những cụm từ dư thừa, vô ích nhất mà tôi đã đọc trong một thời gian, nhưng tôi không biết điều gì đang diễn ra trong tâm trí của người ISO khi họ viết).

+1

Để hoàn thành, trong C++ (không có VLAs) biểu thức không bao giờ được đánh giá: C++ 11, 5.3.3 nói "Toán hạng là một biểu thức, là toán hạng chưa được đánh giá (Điều 5), hoặc một dấu ngoặc đơn loại-id. " –

+0

Chúc mừng, @Mike, kết hợp điều đó vào câu trả lời cho sự hoàn chỉnh. – paxdiablo

10

No. sizeof là một toán tử và hoạt động trên các loại, chứ không phải giá trị thực tế (không được đánh giá).

Để nhắc bạn rằng đó là một toán tử, tôi khuyên bạn nên có thói quen bỏ qua các dấu ngoặc khi thực tế.

int* ptr = 0; 
size_t size = sizeof *ptr; 
size = sizeof (int); /* brackets still required when naming a type */ 
+2

Điều đó và biểu thức không bao giờ được đánh giá - nó chỉ được phân tích cú pháp để xác định loại kết quả. Đối với những gì nó có giá trị, tôi nghĩ rằng '& * ptr' cũng là hợp pháp. –

+0

@ChrisLutz: Cảm ơn bạn, tôi đã kết hợp "không được đánh giá" vào câu trả lời của tôi. –

+0

Tại sao điều quan trọng cần nhớ là nó là một toán tử? – UncleBens

3

sizeof (* ptr) giống như sizeof (int) trong trường hợp này.

+0

Có, nhưng tại sao? Câu trả lời này thiếu một chút gì đó để cho nó đứng ... –

+0

ptr là một con trỏ đến một số nguyên. * ptr là một số nguyên. sizeof (* ptr) là sizeof (số nguyên). – EricS

3

sizeofdecltype không đánh giá toán hạng của chúng, chỉ các loại máy tính.

4

Câu trả lời có thể khác với C, trong đó sizeof không nhất thiết là một cấu trúc biên dịch, nhưng trong C++ biểu thức được cung cấp cho sizeof không bao giờ được đánh giá. Như vậy, không bao giờ có khả năng cho hành vi không xác định để thể hiện bản thân nó. Theo logic tương tự, bạn cũng có thể "gọi" các chức năng không bao giờ được định nghĩa [vì hàm này không bao giờ thực sự được gọi, không cần định nghĩa], một thực tế thường được sử dụng trong các quy tắc SFINAE.

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