2010-06-01 24 views
26

Hoàn dụ:Tại sao một C-Array có giá trị sizeof() sai khi nó được truyền cho một hàm?

#include <stdio.h> 

void test(int arr[]) { 
    int arrSize = (int)(sizeof(arr)/sizeof(arr[0])); 
    printf("%d\n", arrSize); // 2 (wrong?!) 
} 

int main (int argc, const char * argv[]) { 
    int point[3] = {50, 30, 12}; 

    int arrSize = (int)(sizeof(point)/sizeof(point[0])); 
    printf("%d\n", arrSize); // 3 (correct :-)) 

    test(point); 

    return 0; 
} 

Trước khi đi qua nó để một chức năng, sizeof mang lại cho tôi những giá trị đúng. Làm chính xác điều tương tự trên cùng một mảng trong hàm cho kết quả lạ. Có một yếu tố bị thiếu. Tại sao?

Trả lời

37

Khi bạn chuyển một mảng vào một hàm trong C, mảng phân rã thành con trỏ thành phần tử đầu tiên của nó. Khi bạn sử dụng sizeof trên tham số, bạn đang lấy kích thước của con trỏ chứ không phải chính mảng đó.

Nếu bạn cần các chức năng để biết kích thước của mảng, bạn nên vượt qua nó như một tham số riêng biệt:

void test(int arr[], size_t elems) { 
    /* ... */ 
} 

int main(int argc, const char * argv[]) { 
    int point[3] = {50, 30, 12}; 
    /* ... */ 
    test(point, sizeof(point)/sizeof(point[0])); 
    /* ... */ 
} 

Cũng lưu ý rằng, vì một lý do tương tự (lấy sizeof một con trỏ), các sizeof(point)/sizeof(point[0]) lừa không hoạt động đối với mảng được phân bổ động, chỉ một mảng được phân bổ trên ngăn xếp.

2

Bởi vì, khi nó được thông qua, chỉ có con trỏ đến mảng thực sự đang được chuyển.

Câu hỏi của bạn cũng được trả lời tại The C Programming FAQ. Câu hỏi 6.21.

+0

Để trở thành cầu kỳ: Nó là con trỏ đến phần tử thứ nhất của mảng được chuyển. Cùng một giá trị, nhưng loại khác nhau. – alk

0

Vì sizeof() KHÔNG cho bạn biết kích thước của mảng trong C. Nó thực hiện điều gì đó hoàn toàn khác.

sizeof C++ reference

+0

Nếu bạn đã có một cái nhìn gần ví dụ, bạn sẽ thấy rằng tôi không sử dụng sizeof để trực tiếp nhận được số lượng các phần tử trong mảng ... sizeof nên cho tôi biết bao nhiêu bộ nhớ được dành riêng cho mảng ... và trên thực tế phải khớp với số lượng phần tử trong đó, khi kích thước của phần tử được biết. hoặc tôi đang thiếu một cái gì đó? – dontWatchMyProfile

+0

Tôi đã sửa chữa. Nhưng như đã nói ở trên, hãy cẩn thận với con trỏ.Họ cho bạn biết kích thước của chúng, không phải kích thước của loại bạn đang trỏ đến. – PeterK

12

Bởi vì mảng là decayed đến một con trỏ khi thông qua như là đối số chức năng, vì vậy sizeof cung cấp cho bạn 4 và 8 cho các nền tảng 32 bit và 64-bit tương ứng.

6

Ngoài ra, điều quan trọng là phải hiểu rằng sizeof được đánh giá tại thời gian biên dịch. Vì đó là trường hợp, nó không có ý nghĩa để mong đợi đầu ra khác nhau trong test() tùy thuộc vào những gì đã được thông qua. Việc tính toán sizeof được thực hiện khi hàm được biên dịch.

2

Vì trong C, C++ và Objective-C, các hàm không thể thực sự có tham số mảng. Chúng chỉ có thể có tham số trông giống như thông số mảng, nhưng chúng không phải là. Trong ví dụ của bạn,

void test(int arr[]) 

trình biên dịch thấy "có tham số giống như một mảng int" và nó thay thế thông số đó bằng "con trỏ tới int". Vì vậy, các chức năng mà bạn đã viết là hoàn toàn, một trăm phần trăm, giống

void test (int* arr) 

Do đó, bên trong hàm sizeof (arr) sẽ cung cấp cho bạn kích thước của một "con trỏ đến int".

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