2009-10-17 39 views
8

Có vẻ như sizeof không phải là một chức năng thực sự?cơ chế của sizeof() trong C/C++ là gì?

ví dụ, nếu bạn viết như thế này:

int i=0; 
printf("%d\n", sizeof(++i)); 
printf("%d\n", i); 

Bạn có thể nhận được kết quả như sau:

4 
0 

Và khi bạn thâm nhập vào mã lắp ráp, bạn sẽ tìm thấy sth như thế này:

movl  $4, %esi 
leaq  LC0(%rip), %rdi 
xorl %eax, %eax 
call  _printf 

Vì vậy, trình biên dịch đưa trực tiếp hằng số "4" làm tham số của printf thêm gọi nó. Vậy sizeof làm gì?

+6

Lưu ý rằng biểu thức được chuyển đến sizeof không được đánh giá, vì vậy tôi * không * tăng trước. Trông giống như một cách đáng yêu để giới thiệu một lỗi vào (hoặc làm xáo trộn) một số mã. – PaulMcG

Trả lời

34

Bạn biết đấy, có lý do tại sao có standard documents (3.8MB PDF); C99, phần 6.5.3.4, §2:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.


Để đối phó với ibread của nhận xét, đây là một ví dụ cho trường hợp C99 chiều dài biến mảng:

#include <stdio.h> 

size_t sizeof_int_vla(size_t count) 
{ 
    int foo[count]; 
    return sizeof foo; 
} 

int main(void) 
{ 
    printf("%u", (unsigned)sizeof_int_vla(3)); 
} 

Kích thước của foo không còn được biết tại thời gian biên dịch và phải được xác định trong thời gian chạy. Việc lắp ráp được tạo ra trông khá lạ, vì vậy đừng hỏi tôi về chi tiết thực hiện ...

+21

Ngoài ra còn có một lý do khiến stackoverflow.com tồn tại. – jalf

+1

+1 để khai thác đoạn trích –

+1

@jalf: "Dạy một người đàn ông câu cá và bạn nuôi sống anh ta suốt đời. Trừ khi anh ấy không thích sushi — thì bạn cũng phải dạy anh ta nấu ăn." - hoặc một cái gì đó;) – Christoph

8

Sizeof phân tích biểu thức được truyền để tìm loại của nó. Sau đó nó trả về kích thước của loại.

Do kích thước của một kiểu luôn được biết tại thời gian biên dịch, nó được đưa vào mã máy như là một hằng số.

+3

+1 bằng C++ và trước C99. Trong C99, kích thước của một kiểu không phải lúc nào cũng được biết tại thời gian biên dịch: 'void f (int N) {int array [N]; printf ("% d \ n", sizeof (mảng)); } '. Trong trường hợp này, kích thước của mảng không được biết tại thời gian biên dịch nhưng tại thời gian chạy. –

0

Chính xác những gì nó có nghĩa là để làm: đặt trực tiếp hằng số "kích thước của biến/liên tục/loại/etc" vào mã

2

Nó được thay thế bằng hằng số (4 trong trường hợp của bạn) tại thời gian biên dịch . Bởi vì phải mất 4 byte để giữ một int trên nền tảng của bạn.

Và mã của bạn sẽ không biên dịch, thay vì đem lại cho bạn bất kỳ đầu ra ;-) Vì sizoef ;-)

+0

cảm ơn thông báo. Tôi đã sửa lỗi đánh máy. ;) – ibread

+0

bạn được chào đón ;-) –

+0

BTW, nó phụ thuộc vào việc thực hiện, nhưng tôi nghi ngờ hầu hết trong số họ sẽ tạo cuộc gọi đến '_printf' khi thực hiện' toán tử << 'cho cout. –

1

Kích thước của loại trở được tính tại thời gian biên dịch, không có chi phí thời gian chạy

0

sizeof() trả về kích thước tính bằng byte của bất cứ thứ gì bạn truyền làm đối số cho nó. Trong kích thước kiến ​​trúc 32 bit (int) sẽ trả về 4, trong khi sizeof (char) sẽ trả về 1.

1

Trong C++ sizeof() tính toán kích thước của các loại của biểu bên trong nó và thay thế toàn bộ "sizeof() chức năng cuộc gọi" với một hằng số trong quá trình biên dịch.

Biểu thức bên trong sizeof() không bao giờ được đánh giá trong quá trình thực thi chương trình. Và nó thậm chí có thể không phải là một tên kiểu. Kiểm tra các ví dụ sau:

struct X { int i; double j;}; 
int call_to_undefined_function(); 

sizeof(10/0); 
sizeof(((struct X*)NULL)->j); 
sizeof(call_to_undefined_function() + 100); 
sizeof(call_to_undefined_function() + 100.0); 
sizeof(double()/int()); 
16

sizeof là một toán tử chứ không phải hàm.

Đó là thường là được đánh giá là thời gian biên dịch - ngoại lệ là khi được sử dụng trên các mảng độ dài biến kiểu C99.

Ví dụ của bạn đang đánh giá sizeof(int), tất nhiên được biết đến lúc biên dịch, vì vậy mã được thay thế bằng hằng số và do đó ++ không tồn tại trong thời gian chạy được thực hiện.

int i=0; 
cout << sizeof(++i) << endl; 
cout << i << endl; 

Nó cũng đáng chú ý là vì nó là một nhà điều hành, nó có thể được sử dụng mà không có dấu ngoặc trên giá trị:

int myVal; 
cout << sizeof myVal << endl; 
cout << sizeof(myVal) << endl; 

Are tương đương.

+1

có lỗi nhỏ: 'sizeof int' không hợp lệ C vì các loại phải được ngoặc đơn! – Christoph

+0

ah, xin lỗi, đã sửa. –

+1

+1 để nói chính xác đó là toán tử chứ không phải hàm – sbi

0

Bạn tự nói: 'sizeof' không phải là chức năng. Nó là một toán tử tích hợp với cú pháp và ngữ nghĩa đặc biệt (xem các câu trả lời trước đó). Để nhớ tốt hơn mà nó không phải là một chức năng, bạn có thể muốn thoát khỏi những thói quen sử dụng niềng răng thừa và thích sử dụng "braceless" 'sizeof' với các biểu thức như trong ví dụ sau

printf("%d\n", sizeof ++i); 

Đây là chính xác tương đương với phiên bản gốc của bạn.

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