Helpex - Trao đổi & giúp đỡ Đăng nhập
810

Làm cách nào để xác định kích thước của mảng trong C?

Đó là, số phần tử mà mảng có thể giữ?

810 hữu ích 1 bình luận 1.6m xem chia sẻ
21 trả lời 21
1033

Tóm tắt điều hành:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

Câu trả lời đầy đủ:

Để xác định kích thước của mảng theo byte, bạn có thể sử dụng sizeof toán tử:

int a[17];
size_t n = sizeof(a);

Trên máy tính của tôi, ints dài 4 byte, vì vậy n là 68.

Để xác định số lượng phần tử trong mảng, chúng ta có thể chia tổng kích thước của mảng cho kích thước của phần tử mảng. Bạn có thể làm điều này với loại, như thế này:

int a[17];
size_t n = sizeof(a) / sizeof(int);

và nhận được câu trả lời thích hợp (68/4 = 17), nhưng nếu loại athay đổi, bạn sẽ gặp một lỗi khó chịu nếu bạn quên thay đổi sizeof(int).

Vì vậy, ước số được ưu tiên là sizeof(a[0]), kích thước của phần tử zeroeth của mảng.

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

Một ưu điểm khác là bây giờ bạn có thể dễ dàng tham số hóa tên mảng trong một macro và nhận:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);
1033 hữu ích 5 bình luận chia sẻ
696

Các sizeofcách là con đường đúng khi và chỉ khi bạn đang đối phó với mảng chưa nhận được như các thông số. Một mảng được gửi dưới dạng tham số cho hàm được coi là một con trỏ, do đó sizeofsẽ trả về kích thước của con trỏ, thay vì của mảng.

Vì vậy, bên trong các chức năng phương pháp này không hoạt động. Thay vào đó, luôn luôn vượt qua một tham số bổ sung size_t sizecho biết số lượng phần tử trong mảng.

Kiểm tra:

#include <stdio.h>
#include <stdlib.h>

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

Đầu ra (trong HĐH Linux 64 bit):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

Đầu ra (trong hệ điều hành windows 32 bit):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
696 hữu ích 5 bình luận chia sẻ
116

Điều đáng chú ý là sizeofkhông giúp ích gì khi xử lý một giá trị mảng đã phân rã thành một con trỏ: mặc dù nó trỏ đến phần đầu của một mảng, nhưng trình biên dịch nó giống như một con trỏ tới một phần tử của mảng đó . Một con trỏ không "nhớ" bất cứ điều gì khác về mảng đã được sử dụng để khởi tạo nó.

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
116 hữu ích 2 bình luận chia sẻ
42

"Bí quyết" sizeof là cách tốt nhất mà tôi biết, với một điều nhỏ nhưng (với tôi, đây là một tiểu cảnh thú cưng lớn) thay đổi quan trọng trong việc sử dụng dấu ngoặc đơn.

Vì mục Wikipedia cho thấy rõ, C's sizeofkhông phải là một hàm; đó là một nhà điều hành . Vì vậy, nó không yêu cầu dấu ngoặc đơn xung quanh đối số của nó, trừ khi đối số là tên loại. Điều này rất dễ nhớ, vì nó làm cho đối số trông giống như một biểu thức truyền, cũng sử dụng dấu ngoặc đơn.

Vì vậy: Nếu bạn có những điều sau đây:

int myArray[10];

Bạn có thể tìm thấy số lượng phần tử với mã như thế này:

size_t n = sizeof myArray / sizeof *myArray;

Điều đó, với tôi, đọc dễ dàng hơn nhiều so với thay thế bằng dấu ngoặc đơn. Tôi cũng thích sử dụng dấu hoa thị ở phần bên phải của bộ phận, vì nó ngắn gọn hơn là lập chỉ mục.

Tất nhiên, đây cũng là thời gian biên dịch, vì vậy không cần phải lo lắng về việc phân chia ảnh hưởng đến hiệu suất của chương trình. Vì vậy, sử dụng hình thức này bất cứ nơi nào bạn có thể.

Tốt nhất là luôn sử dụng sizeof trên một đối tượng thực tế khi bạn có một đối tượng, thay vì trên một loại, từ đó bạn không cần phải lo lắng về việc gây ra lỗi và nêu sai loại.

Chẳng hạn, giả sử bạn có một hàm xuất một số dữ liệu dưới dạng luồng byte, ví dụ trên toàn mạng. Chúng ta hãy gọi hàm send()và làm cho nó lấy làm đối số một con trỏ tới đối tượng cần gửi và số byte trong đối tượng. Vì vậy, nguyên mẫu trở thành:

void send(const void *object, size_t size);

Và sau đó bạn cần gửi một số nguyên, vì vậy bạn mã hóa nó như thế này:

int foo = 4711;
send(&foo, sizeof (int));

Bây giờ, bạn đã giới thiệu một cách tinh tế để tự bắn vào chân mình, bằng cách chỉ định loại fooở hai nơi. Nếu cái này thay đổi nhưng cái kia thì không, mã bị hỏng. Vì vậy, luôn luôn làm điều đó như thế này:

send(&foo, sizeof foo);

Bây giờ bạn được bảo vệ. Chắc chắn, bạn nhân đôi tên của biến, nhưng điều đó có xác suất phá vỡ cao theo cách trình biên dịch có thể phát hiện, nếu bạn thay đổi nó.

42 hữu ích 4 bình luận chia sẻ
35
int size = (&arr)[1] - arr;

Kiểm tra liên kết này để giải thích

35 hữu ích 4 bình luận chia sẻ
24

Bạn có thể sử dụng toán tử sizeof nhưng nó sẽ không hoạt động cho các hàm vì nó sẽ lấy tham chiếu của con trỏ mà bạn có thể làm như sau để tìm độ dài của một mảng:

len = sizeof(arr)/sizeof(arr[0])

Mã ban đầu được tìm thấy ở đây: Chương trình C để tìm số lượng phần tử trong một mảng

24 hữu ích 0 bình luận chia sẻ
20

Nếu bạn biết kiểu dữ liệu của mảng, bạn có thể sử dụng một cái gì đó như:

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};

int noofele = sizeof(arr)/sizeof(int);

Hoặc nếu bạn không biết kiểu dữ liệu của mảng, bạn có thể sử dụng một cái gì đó như:

noofele = sizeof(arr)/sizeof(arr[0]);

Lưu ý: Điều này chỉ hoạt động nếu mảng không được xác định trong thời gian chạy (như malloc) và mảng không được truyền trong hàm. Trong cả hai trường hợp, arr(tên mảng) là một con trỏ.

20 hữu ích 1 bình luận chia sẻ
15

Macro ARRAYELEMENTCOUNT(x)mà mọi người đang sử dụng đánh giá không chính xác . Trên thực tế, đây chỉ là một vấn đề nhạy cảm, bởi vì bạn không thể có các biểu thức dẫn đến loại 'mảng'.

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))

ARRAYELEMENTCOUNT(p + 1);

Thực tế đánh giá là:

(sizeof (p + 1) / sizeof (p + 1[0]));

Trong khi

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])

ARRAYELEMENTCOUNT(p + 1);

Nó đánh giá chính xác để:

(sizeof (p + 1) / sizeof (p + 1)[0]);

Điều này thực sự không liên quan nhiều đến kích thước của mảng một cách rõ ràng. Tôi vừa nhận thấy rất nhiều lỗi từ việc không thực sự quan sát cách bộ xử lý C hoạt động. Bạn luôn bao bọc tham số macro, không thể tham gia vào biểu thức.


Chính xác; ví dụ của tôi là một trong những xấu. Nhưng đó thực sự là chính xác những gì sẽ xảy ra. Như tôi đã đề cập trước đây p + 1sẽ kết thúc dưới dạng một con trỏ và làm mất hiệu lực toàn bộ macro (giống như khi bạn cố gắng sử dụng macro trong một hàm với tham số con trỏ).

Vào cuối ngày, trong trường hợp cụ thể này , lỗi không thực sự quan trọng (vì vậy tôi chỉ lãng phí thời gian của mọi người; huzzah!), Vì bạn không có biểu thức với một loại 'mảng'. Nhưng thực sự quan điểm về các đánh giá tiền xử lý tôi nghĩ là một điều quan trọng.

15 hữu ích 3 bình luận chia sẻ
14

Đối với mảng nhiều chiều, nó phức tạp hơn một chút. Mọi người thường định nghĩa các hằng vĩ mô rõ ràng, nghĩa là

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

Nhưng các hằng số này có thể được đánh giá tại thời gian biên dịch với sizeof :

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

Lưu ý rằng mã này hoạt động trong C và C ++. Đối với các mảng có nhiều hơn hai chiều sử dụng

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

vv, quảng cáo vô hạn.

14 hữu ích 0 bình luận chia sẻ
14

Kích thước của một mảng trong C:

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          
                                       // Size of each element = size of type
14 hữu ích 4 bình luận chia sẻ
12
sizeof(array) / sizeof(array[0])
12 hữu ích 0 bình luận chia sẻ
10
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
10 hữu ích 1 bình luận chia sẻ
9

"bạn đã giới thiệu một cách tinh tế để tự bắn vào chân mình"

Mảng C 'bản địa' không lưu trữ kích thước của chúng. Do đó, nên lưu chiều dài của mảng trong một biến / const riêng biệt và truyền nó bất cứ khi nào bạn vượt qua mảng, đó là:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

Bạn NÊN luôn luôn tránh các mảng bản địa (trừ khi bạn không thể, trong trường hợp đó, chú ý đến bàn chân của bạn). Nếu bạn đang viết C ++, hãy sử dụng bộ chứa 'vectơ' của STL . "So với mảng, chúng cung cấp hiệu năng gần như tương tự" và chúng hữu ích hơn nhiều!

// vector is a template, the <int> means it is a vector of ints
vector<int> numbers;  

// push_back() puts a new value at the end (or back) of the vector
for (int i = 0; i < 10; i++)
    numbers.push_back(i);

// Determine the size of the array
cout << numbers.size();

Xem: http://www.cplusplus.com/reference/stl/vector/

9 hữu ích 2 bình luận chia sẻ
4

@ Magnus: Tiêu chuẩn định nghĩa sizeof là thu được số byte trong đối tượng và sizeof (char) luôn là một. Số lượng bit trong một byte là cụ thể thực hiện.

Chỉnh sửa: Phần tiêu chuẩn ANSI C ++ 5.3.3 Sizeof:

Toán tử sizeof mang lại số byte trong biểu diễn đối tượng của toán hạng của nó. [...] sizeof (char), sizeof (char đã ký) và sizeof (uns uns char) là 1; kết quả của sizeof được áp dụng cho bất kỳ loại cơ bản nào khác được xác định theo triển khai.

Mục 1.6 Mô hình bộ nhớ C ++:

Đơn vị lưu trữ cơ bản trong mô hình bộ nhớ C ++ là byte. Một byte ít nhất đủ lớn để chứa bất kỳ thành viên nào của bộ ký tự thực hiện cơ bản và bao gồm một chuỗi các bit liền kề nhau, số lượng được xác định theo cách thực hiện.

4 hữu ích 1 bình luận chia sẻ
4

@Skizz: Tôi khá chắc chắn rằng mình đúng, mặc dù "nguồn" tốt nhất tôi có thể cung cấp cho bạn tại thời điểm này là Wikipedia, từ bài viết trên sizeof:

Wikipedia là sai, Skizz là đúng. sizeof (char) là 1, theo định nghĩa.

Ý tôi là, chỉ cần đọc mục Wikipedia thật chặt chẽ để thấy rằng nó sai. "bội số của char". sizeof(char)không bao giờ có thể là bất cứ điều gì khác ngoài "1". Nếu nó là, giả sử, 2, nó có nghĩa sizeof(char)là gấp đôi kích thước của char!

4 hữu ích 2 bình luận chia sẻ
4

Nếu bạn thực sự muốn làm điều này để vượt qua mảng của mình, tôi khuyên bạn nên thực hiện một cấu trúc để lưu trữ một con trỏ đến loại bạn muốn một mảng và một số nguyên biểu thị kích thước của mảng. Sau đó, bạn có thể chuyển điều đó xung quanh các chức năng của bạn. Chỉ cần gán giá trị biến mảng (con trỏ cho phần tử đầu tiên) cho con trỏ đó. Sau đó, bạn có thể đi Array.arr[i]lấy phần tử thứ i và sử dụng Array.sizeđể lấy số phần tử trong mảng.

Tôi bao gồm một số mã cho bạn. Nó không hữu ích lắm nhưng bạn có thể mở rộng nó với nhiều tính năng hơn. Thành thật mà nói, nếu đây là những điều bạn muốn, bạn nên ngừng sử dụng C và sử dụng ngôn ngữ khác với các tính năng này được tích hợp.

/* Absolutely no one should use this...
   By the time you're done implementing it you'll wish you just passed around
   an array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and 
   cut out the array in main by using the stdlib memory allocation methods,
   but it will work much slower since it will store your array on the heap */

#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h 
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{
   int age;
   char name[20];
} MyType;
typedef struct MyTypeArray
{
   int size;
   MyType *arr;
} MyTypeArray;

MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h */

/* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{
   MyType d;
   d.age = age;
   strcpy(d.name, name);
   return d;
}

MyTypeArray new_MyTypeArray(int size, MyType *first)
{
   MyTypeArray d;
   d.size = size;
   d.arr = first;
   return d;
}
/* End MyTypeArray.c */


void print_MyType_names(MyTypeArray d)
{
   int i;
   for (i = 0; i < d.size; i++)
   {
      printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);
   }
}

int main()
{
   /* First create an array on the stack to store our elements in.
      Note we could create an empty array with a size instead and
      set the elements later. */
   MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};
   /* Now create a "MyTypeArray" which will use the array we just
      created internally. Really it will just store the value of the pointer
      "arr". Here we are manually setting the size. You can use the sizeof
      trick here instead if you're sure it will work with your compiler. */
   MyTypeArray array = new_MyTypeArray(2, arr);
   /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
   print_MyType_names(array);
   return 0;
}
4 hữu ích 1 bình luận chia sẻ
3

Cách tốt nhất là bạn lưu thông tin này, ví dụ, trong một cấu trúc:

typedef struct {
     int *array;
     int elements;
} list_s;

Thực hiện tất cả các chức năng cần thiết như tạo, hủy, kiểm tra sự bình đẳng và mọi thứ khác bạn cần. Nó là dễ dàng hơn để vượt qua như là một tham số.

3 hữu ích 1 bình luận chia sẻ
3

Hàm sizeoftrả về số byte được sử dụng bởi mảng của bạn trong bộ nhớ. Nếu bạn muốn tính số lượng phần tử trong mảng của mình, bạn nên chia số đó với sizeofloại biến của mảng. Giả sử int array[10];, nếu số nguyên loại biến trong máy tính của bạn là 32 bit (hoặc 4 byte), để có được kích thước của mảng, bạn nên làm như sau:

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);
3 hữu ích 0 bình luận chia sẻ
1

Bạn có thể sử dụng &toán tử. Đây là mã nguồn:

#include<stdio.h>
#include<stdlib.h>
int main(){

    int a[10];

    int *p; 

    printf("%p\n", (void *)a); 
    printf("%p\n", (void *)(&a+1));
    printf("---- diff----\n");
    printf("%zu\n", sizeof(a[0]));
    printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));


    return 0;
};

Đây là đầu ra mẫu

1549216672
1549216712
---- diff----
4
The size of array a is 10
1 hữu ích 4 bình luận chia sẻ
1
int a[10];
int size = (*(&a+1)-a) ;

Để biết thêm chi tiết xem tại đây và cũng ở đây .

1 hữu ích 3 bình luận chia sẻ
0

Sao mà mấy người trả lời ở trên giống kiểu máy móc thế nhỉ?

Tên thì là tên người Việt nhưng mà vẫn có cảm giác không phải là thật. Câu từ nhiều chỗ giống như dùng google dịch. Có phải là ảo không vậy mn?

0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ c arrays memory , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading