Tại sao sizeof được coi là một toán tử?


93

Tại sao được sizeofcoi là toán tử mà không phải là hàm?

Thuộc tính nào là cần thiết để đủ điều kiện làm nhà điều hành?

Câu trả lời:


181

Bởi vì tiêu chuẩn C nói như vậy, và nó nhận được phiếu bầu duy nhất.

Do hậu quả:

  • Toán hạng của sizeof có thể là kiểu trong ngoặc đơn sizeof (int), thay vì một biểu thức đối tượng.
  • Dấu ngoặc đơn là không cần thiết: int a; printf("%d\n", sizeof a);hoàn toàn ổn. Chúng thường được nhìn thấy, thứ nhất vì chúng cần thiết như một phần của biểu thức ép kiểu và thứ hai vì sizeof có mức độ ưu tiên rất cao, vì vậy sizeof a + bkhông giống với sizeof (a+b). Nhưng chúng không phải là một phần của lệnh gọi sizeof, chúng là một phần của toán hạng.
  • Bạn không thể lấy địa chỉ của sizeof.
  • Biểu thức là toán hạng của sizeof không được đánh giá trong thời gian chạy ( sizeof a++không sửa đổi a).
  • Biểu thức là toán hạng của sizeof có thể có bất kỳ kiểu nào ngoại trừ kiểu void hoặc hàm. Thật vậy, đó là loại điểm của kích thước.

Một chức năng sẽ khác nhau về tất cả những điểm đó. Có thể có những khác biệt khác giữa hàm và toán tử một ngôi, nhưng tôi nghĩ điều đó đủ để cho thấy tại sao sizeof không thể là một hàm ngay cả khi có lý do để muốn nó như vậy.


3
Chà, đúng như những gì tôi đang nghĩ!
crashmstr

7
Không thể nói nó tốt hơn.
Clement Herreman

Tôi tin rằng mọi thứ ngày nay phức tạp hơn do các mảng có độ dài thay đổi (VLA). IIRC, tiêu chuẩn thậm chí sẽ cho phép sizeofcó tác dụng phụ nếu có VLA trong biểu thức.
Aaron McDaid

@glglgl Không, điều đó không có ý nghĩa gì. Trong bối cảnh đó, (int)không có gì là lạ mắt - chỉ là tên của một kiểu bên trong dấu ngoặc đơn. Dấu ngoặc đơn ở đây là một phần của cú pháp sizeof- chúng được yêu cầu khi lấy kích thước của một kiểu, nhưng không bắt buộc khi lấy kích thước của một biểu thức. Xem ví dụ ở đây
anatolyg

1
Tiêu chuẩn sử dụng hai ký hiệu sizeof: sizeof unary-expressionsizeof ( type-name )- vì vậy trong tiêu chuẩn C11, nó không được coi là 'kiểu đúc' mà là một tên kiểu được đặt trong ngoặc đơn. Kết quả thực là giống nhau. (Để so sánh, một biểu thức diễn viên là ( type-name ) cast-expression.) Và tôi ghét cách nhận xét đó Markdown hoạt động khác với Q&A Markdown!
Jonathan Leffler,

24

Nó có thể được sử dụng như một hằng số thời gian biên dịch, điều này chỉ khả thi nếu nó là một toán tử hơn là một hàm. Ví dụ:

union foo {
    int i;
    char c[sizeof(int)];
};

Về mặt cú pháp, nếu nó không phải là một toán tử thì nó sẽ phải là một macro tiền xử lý vì các hàm không thể nhận kiểu làm đối số. Đó sẽ là một macro khó thực hiện vì sizeofcó thể lấy cả kiểu và biến làm đối số.


4
+1 nhưng lưu ý rằng nó không phải là hằng số thời gian biên dịch khi đối số là VLA - mảng có độ dài thay đổi.
Jonathan Leffler

6

Bởi vì tiêu chuẩn C nói như vậy, và nó nhận được phiếu bầu duy nhất.

Và tiêu chuẩn có thể đúng vì sizeofcó một loại và

Nói chung, nếu miền hoặc miền đồng (hoặc cả hai) của một hàm chứa các phần tử phức tạp hơn đáng kể so với số thực, thì hàm đó được gọi là toán tử. Ngược lại, nếu cả miền và miền của một hàm đều không chứa các phần tử phức tạp hơn số thực, thì hàm đó có thể được gọi đơn giản là một hàm. Các hàm lượng giác như cosin là ví dụ của trường hợp sau.

Ngoài ra, khi các hàm được sử dụng thường xuyên đến mức chúng đã phát triển nhanh hơn hoặc dễ dàng hơn so với dạng F (x, y, z, ...) chung, các dạng đặc biệt thu được cũng được gọi là toán tử. Ví dụ bao gồm các toán tử tiền tố như phép cộng "+" và phép chia "/", và các toán tử hậu tố như giai thừa "!". Việc sử dụng này không liên quan đến sự phức tạp của các thực thể liên quan.

(Wikipedia)


Điều này có lẽ giải thích động lực của tiêu chuẩn C (và các ngôn ngữ lập trình khác) trong việc sử dụng các thuật ngữ "toán tử" và "chức năng" như chúng.
Steve Jessop

5

Bởi vì nó không phải là một chức năng. Bạn có thể sử dụng nó như vậy:

int a;
printf("%d\n", sizeof a);

Chức năng có điểm nhập, mã, v.v. Chức năng sẽ được chạy trong thời gian chạy (hoặc nội tuyến), kích thước của nó phải được xác định tại thời điểm biên dịch.


2

toán tử sizeof là thực thể thời gian biên dịch không phải thời gian chạy và không cần dấu ngoặc đơn như một hàm. Khi mã được biên dịch thì nó thay thế giá trị bằng kích thước của biến đó tại thời điểm biên dịch nhưng trong hàm sau khi hàm được thực thi thì chúng ta sẽ biết giá trị trả về.


1

Bởi vì:

  • khi bạn truyền một giá trị cho một hàm, kích thước của đối tượng sẽ không được chuyển cho hàm, vì vậy một sizeof"hàm" sẽ không có cách nào xác định kích thước
  • trong C, các hàm chỉ có thể chấp nhận một loại đối số; sizeof () cần phải chấp nhận tất cả các loại khác nhau (các biến cũng như các loại! Bạn không thể chuyển một loại cho một hàm trong C)
  • gọi một hàm liên quan đến việc tạo bản sao của các đối số và các chi phí không cần thiết khác

1

Có một sự khác biệt nhỏ từ hàm - giá trị của sizeof được giải quyết trong thời gian biên dịch, nhưng không phải trong thời gian chạy!


7
Ngoại trừ VLA - mảng có độ dài thay đổi - các đối số.
Jonathan Leffler

1

Bởi vì nó là một toán tử thời gian biên dịch , để tính toán kích thước của một đối tượng, yêu cầu thông tin kiểu chỉ có sẵn tại thời gian biên dịch. Điều này không phù hợp với C ++.


0

sizeof()toán tử là thời gian biên dịch sẽ xảy ra. Nó có thể được sử dụng để xác định các tham số hoặc đối số.


-1

Sizeof (), tôi nghĩ rõ ràng nó vừa là một hàm vừa là một toán tử. Tại sao? Bởi vì một hàm giữ dấu ngoặc đơn cho mục nhập ở giai đoạn nhập. Nhưng chủ yếu cũng là một toán tử nguyên nhân các toán tử là ký tự hành động, do đó sizeof là một câu lệnh hành động hoạt động trên toán hạng trong dấu ngoặc đơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.