C에서 배열의 크기를 어떻게 결정합니까?
즉, 배열이 보유할 수 있는 요소의 수는?
질문자 :Mark Harrison
C에서 배열의 크기를 어떻게 결정합니까?
즉, 배열이 보유할 수 있는 요소의 수는?
요약:
int a[17]; size_t n = sizeof(a)/sizeof(a[0]);
전체 답변:
배열의 크기를 바이트 단위로 결정하려면 sizeof
연산자를 사용할 수 있습니다.
int a[17]; size_t n = sizeof(a);
내 컴퓨터에서 int는 4바이트이므로 n은 68입니다.
배열의 요소 수를 결정하기 위해 배열의 전체 크기를 배열 요소의 크기로 나눌 수 있습니다. 다음과 같이 유형으로 이 작업을 수행할 수 있습니다.
int a[17]; size_t n = sizeof(a) / sizeof(int);
적절한 대답 (4분의 68 = 17)을 얻을 수 있지만, 유형 경우 a
변경하면 변경 잊어 버린 경우 당신은 불쾌한 버그가있을 것 sizeof(int)
잘한다.
따라서 선호되는 제수는 sizeof(a[0])
또는 배열의 첫 번째 요소 크기인 sizeof(*a)
int a[17]; size_t n = sizeof(a) / sizeof(a[0]);
또 다른 이점은 이제 매크로에서 배열 이름을 쉽게 매개변수화하고 다음을 얻을 수 있다는 것입니다.
#define NELEMS(x) (sizeof(x) / sizeof((x)[0])) int a[17]; size_t n = NELEMS(a);
sizeof
방법은 매개변수로 수신되지 않은 배열을 처리 하는 경우 올바른 방법입니다. 함수에 매개변수로 보낸 배열은 포인터로 취급되므로 sizeof
는 배열 대신 포인터의 크기를 반환합니다.
따라서 함수 내부에서는 이 방법이 작동하지 않습니다. 대신 항상 배열의 요소 수를 나타내는 추가 매개변수 size_t size
시험:
#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]) )); }
출력(64비트 Linux OS에서):
sizeof of array: 28 sizeof of parameter: 8 Length of array: 7 Length of parameter: 2
출력(32비트 Windows OS에서):
sizeof of array: 28 sizeof of parameter: 4 Length of array: 7 Length of parameter: 1
sizeof
는 포인터로 소멸된 배열 값을 처리할 때 도움이 되지 않는다는 점에 주목할 가치가 있습니다. 배열의 시작을 가리키더라도 컴파일러에게는 해당 배열의 단일 요소에 대한 포인터와 같습니다. 정렬. 포인터는 초기화에 사용된 배열에 대해 다른 것을 "기억"하지 않습니다.
int a[10]; int* p = a; assert(sizeof(a) / sizeof(a[0]) == 10); assert(sizeof(p) == sizeof(int*)); assert(sizeof(*p) == sizeof(int));
sizeof
"trick"은 내가 아는 가장 좋은 방법으로, 괄호 사용에 있어 작지만 (나에게 이것은 중요한 문제인) 중요한 변화입니다.
Wikipedia 항목에서 분명히 알 수 있듯이 C의 sizeof
는 함수가 아닙니다. 운영자 입니다. 따라서 인수가 유형 이름이 아닌 경우 인수 주위에 괄호가 필요하지 않습니다. 이것은 인수를 괄호를 사용하는 캐스트 표현식처럼 보이게 하기 때문에 기억하기 쉽습니다.
따라서: 다음이 있는 경우:
int myArray[10];
다음과 같은 코드로 요소 수를 찾을 수 있습니다.
size_t n = sizeof myArray / sizeof *myArray;
그것은 나에게 괄호가있는 대안보다 훨씬 쉽게 읽습니다. 나는 또한 인덱싱보다 더 간결하기 때문에 분할의 오른쪽 부분에 별표를 사용하는 것을 선호합니다.
물론 이것은 모두 컴파일 타임이므로 프로그램의 성능에 영향을 미치는 분할에 대해 걱정할 필요가 없습니다. 따라서 가능하면 이 양식을 사용하십시오.
sizeof
를 사용하는 것이 항상 가장 좋습니다. 그러면 오류를 만들고 잘못된 유형을 언급하는 것에 대해 걱정할 필요가 없기 때문입니다.
예를 들어 네트워크를 통해 일부 데이터를 바이트 스트림으로 출력하는 함수가 있다고 가정해 보겠습니다. send()
함수를 호출하고 보낼 객체에 대한 포인터와 객체의 바이트 수를 인수로 사용하도록 합시다. 따라서 프로토타입은 다음과 같습니다.
void send(const void *object, size_t size);
그런 다음 정수를 보내야 하므로 다음과 같이 코딩합니다.
int foo = 4711; send(&foo, sizeof (int));
이제 두 곳에서 foo
유형을 지정하여 발을 직접 쏘는 미묘한 방법을 소개했습니다. 하나는 변경되지만 다른 하나는 변경되지 않으면 코드가 중단됩니다. 따라서 항상 다음과 같이 하십시오.
send(&foo, sizeof foo);
이제 당신은 보호됩니다. 물론 변수 이름을 복제하지만 변경하면 컴파일러가 감지할 수 있는 방식으로 손상될 가능성이 높습니다.
int size = (&arr)[1] - arr;
설명은 이 링크 를 확인하세요
sizeof
(사용할 수 있다 하더라도)를 사용하지 않는 것이 좋습니다. 배열의 두 가지 다른 크기 중 하나를 요소 수 또는 바이트 단위로 가져옵니다. 이는 여기에서 마지막 두 가지 경우입니다. 두 가지 크기 각각에 대해 아래 표시된 매크로를 사용하여 더 안전하게 만들 수 있습니다. 그 이유는 메인테이너에게 코드의 의도를 분명히 하고 sizeof(arr)
sizeof(ptr)
차이를 언뜻 보기에(이 방법으로 작성된 것이 명확하지 않음) 코드를 읽는 모든 사람에게 버그가 명백하도록 하기 위함입니다. .
TL;DR:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + must_be_array(arr)) #define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr)) #define ARRAY_BYTES(arr) (sizeof(arr) + must_be_array(arr)) #define ARRAY_SBYTES(arr) ((ssize_t)ARRAY_BYTES(arr))
must_be_array(arr)
(아래 정의) -Wsizeof-pointer-div
가 버그가 있으므로 필요합니다(2020년 4월 기준).
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define is_array(arr) (!is_same_type((arr), &(arr)[0])) #define must_be(e, ...) ( \ 0 * (int)sizeof( \ struct { \ _Static_assert((e) __VA_OPT__(,) __VA_ARGS__);\ char ISO_C_forbids_a_struct_with_no_members__; \ } \ ) \ ) #define must_be_array(arr) must_be(is_array(arr))
이 주제와 관련하여 중요한 버그가 있습니다: https://lkml.org/lkml/2015/9/3/428
나는 함수의 매개변수에 대해 배열 표기법을 사용하지 않는 Linus가 제공하는 솔루션에 동의하지 않습니다.
포인터가 배열로 사용되고 있다는 문서로 배열 표기법을 좋아합니다. 그러나 이는 버그가 있는 코드를 작성하는 것이 불가능하도록 완벽한 솔루션을 적용해야 함을 의미합니다.
배열에서 알고 싶은 세 가지 크기가 있습니다.
첫 번째 것은 매우 간단하고 배열이나 포인터를 다루는 것과 같은 방식으로 처리되기 때문에 중요하지 않습니다.
사용 예:
void foo(ptrdiff_t nmemb, int arr[static nmemb]) { qsort(arr, nmemb, sizeof(arr[0]), cmp); }
qsort()
는 이 값을 세 번째 인수로 필요로 합니다.
질문의 주제인 다른 두 크기의 경우 배열을 처리하고 있는지 확인하고 그렇지 않은 경우 컴파일을 중단해야 합니다. 포인터를 처리하는 경우 잘못된 값을 얻게 되기 때문입니다. . 컴파일이 중단되면 배열이 아니라 포인터를 사용한다는 것을 쉽게 알 수 있습니다. 포인터 뒤에 배열.
이것은 가장 일반적이며 많은 답변에서 일반적인 매크로 ARRAY_SIZE
.
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
ARRAY_SIZE
ptrdiff_t
유형의 부호 있는 변수와 함께 일반적으로 사용된다는 점을 감안할 때 이 매크로의 부호 있는 변형을 정의하는 것이 좋습니다.
#define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr))
PTRDIFF_MAX
이상의 구성원이 있는 배열은 이 서명된 매크로 버전에 대해 잘못된 값을 제공하지만 C17::6.5.6.9를 읽을 때 이와 같은 배열은 이미 불장난을 하고 있습니다. 이 경우 ARRAY_SIZE
및 size_t
만 사용해야 합니다.
GCC 8과 같은 최신 버전의 컴파일러는 이 매크로를 포인터에 적용할 때 경고하므로 안전합니다(이전 컴파일러에서 안전하게 만드는 다른 방법이 있음).
전체 배열의 바이트 크기를 각 요소의 크기로 나누어 작동합니다.
사용 예:
void foo(ptrdiff_t nmemb) { char buf[nmemb]; fgets(buf, ARRAY_SIZE(buf), stdin); } void bar(ptrdiff_t nmemb) { int arr[nmemb]; for (ptrdiff_t i = 0; i < ARRAY_SSIZE(arr); i++) arr[i] = i; }
이러한 함수가 배열을 사용하지 않고 대신 매개변수로 가져오면 이전 코드가 컴파일되지 않으므로 버그가 있을 수 없습니다(최신 컴파일러 버전을 사용하거나 다른 트릭을 사용하는 경우). , 매크로 호출을 값으로 대체해야 합니다.
void foo(ptrdiff_t nmemb, char buf[nmemb]) { fgets(buf, nmemb, stdin); } void bar(ptrdiff_t nmemb, int arr[nmemb]) { for (ptrdiff_t i = 0; i < nmemb; i++) arr[i] = i; }
ARRAY_SIZE
는 일반적으로 앞의 경우에 대한 솔루션으로 사용되지만 이 경우는 덜 일반적이기 때문에 안전하게 작성되는 경우가 거의 없습니다.
이 값을 얻는 일반적인 방법은 sizeof(arr)
를 사용하는 것입니다. 문제: 이전 문제와 동일합니다. 배열 대신 포인터가 있으면 프로그램이 엉망이 됩니다.
문제에 대한 해결책은 이전과 동일한 매크로를 사용하는 것입니다. 이 매크로는 안전하다고 알고 있습니다(포인터에 적용되는 경우 컴파일이 중단됨).
#define ARRAY_BYTES(arr) (sizeof((arr)[0]) * ARRAY_SIZE(arr))
ssize_t
를 반환하는 함수의 출력과 비교된다는 점을 감안할 때 이 매크로의 부호 있는 변형을 정의하는 것이 좋습니다.
#define ARRAY_SBYTES(arr) ((ssize_t)ARRAY_BYTES(arr))
작동 방식은 매우 간단합니다. ARRAY_SIZE
가 수행하는 나눗셈을 취소하므로 수학적 취소 후에는 하나의 sizeof(arr)
ARRAY_SIZE
구성의 안전성이 추가됩니다.
사용 예:
void foo(ptrdiff_t nmemb) { int arr[nmemb]; memset(arr, 0, ARRAY_BYTES(arr)); }
memset()
이 값이 세 번째 인수로 필요합니다.
이전과 마찬가지로 배열이 매개변수(포인터)로 수신되면 컴파일되지 않으며 매크로 호출을 값으로 대체해야 합니다.
void foo(ptrdiff_t nmemb, int arr[nmemb]) { memset(arr, 0, sizeof(arr[0]) * nmemb); }
-Wsizeof-pointer-div
가 버그가 있습니다 . 오늘 저는 GCC의 새로운 경고가 시스템 헤더가 아닌 헤더에 매크로가 정의된 경우에만 작동한다는 것을 알게 되었습니다. 시스템에 설치된 헤더에 매크로를 정의하면(보통 /usr/local/include/
또는 /usr/include/
)( #include <foo.h>
), 컴파일러는 경고를 표시하지 않습니다. GCC 9.3.0).
그래서 우리는 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
를 가지고 있고 그것을 안전하게 만들고 싶습니다. _Static_assert()
및 일부 GCC 확장이 필요 합니다. Statements and Declarations in Expressions , __builtin_types_compatible_p :
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define is_array(arr) (!is_same_type((arr), &(arr)[0])) #define Static_assert_array(arr) _Static_assert(is_array(arr)) #define ARRAY_SIZE(arr) ( \ { \ Static_assert_array(arr); \ sizeof(arr) / sizeof((arr)[0]); \ } \ )
이제 ARRAY_SIZE()
는 완전히 안전하므로 모든 파생물이 안전합니다.
__arraycount()
제공: Libbsd <sys/cdefs.h>
에 __arraycount()
를 제공합니다. 이는 한 쌍의 괄호가 없기 때문에 안전하지 않지만 이러한 괄호를 직접 추가할 수 있으므로 헤더에 나눗셈을 작성할 필요조차 없습니다. (이미 존재하는 코드를 복제하는 이유는 무엇입니까?). 해당 매크로는 시스템 헤더에 정의되어 있으므로 사용하는 경우 위의 매크로를 사용해야 합니다.
#include <stddef.h> #include <sys/cdefs.h> #include <sys/types.h> #define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define is_array(arr) (!is_same_type((arr), &(arr)[0])) #define Static_assert_array(arr) _Static_assert(is_array(arr)) #define ARRAY_SIZE(arr) ( \ { \ Static_assert_array(arr); \ __arraycount((arr)); \ } \ ) #define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr)) #define ARRAY_BYTES(arr) (sizeof((arr)[0]) * ARRAY_SIZE(arr)) #define ARRAY_SBYTES(arr) ((ssize_t)ARRAY_BYTES(arr))
일부 시스템은 <sys/param.h>
에 nitems()
를 제공하고 일부 시스템은 둘 다 제공합니다. 시스템을 확인하고 가지고 있는 시스템을 사용해야 하며 이식성과 지원을 위해 일부 전처리기 조건문을 사용해야 합니다.
유감스럽게도 ({})
gcc 확장자는 파일 범위에서 사용할 수 없습니다. 파일 범위에서 매크로를 사용할 수 있으려면 정적 어설션이 sizeof(struct {})
안에 있어야 합니다. 그런 다음 결과에 영향을 미치지 않도록 0
(int)
로의 캐스트 (int)0
을 반환하는 함수를 시뮬레이션하는 데 유용할 수 있습니다(이 경우에는 필요하지 않지만 다른 용도로 재사용할 수 있음).
ARRAY_BYTES()
의 정의를 약간 단순화할 수 있습니다.
#include <stddef.h> #include <sys/cdefs.h> #include <sys/types.h> #define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define is_array(arr) (!is_same_type((arr), &(arr)[0])) #define must_be(e, ...) ( \ 0 * (int)sizeof( \ struct { \ _Static_assert((e) __VA_OPT__(,) __VA_ARGS__);\ char ISO_C_forbids_a_struct_with_no_members__; \ } \ ) \ ) #define must_be_array(arr) must_be(is_array(arr)) #define ARRAY_SIZE(arr) (__arraycount((arr)) + must_be_array(arr)) #define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr)) #define ARRAY_BYTES(arr) (sizeof(arr) + must_be_array(arr)) #define ARRAY_SBYTES(arr) ((ssize_t)ARRAY_BYTES(arr))
이 코드는 완전히 필요한 다음 확장을 사용하며, 그 존재는 안전을 위해 절대적으로 필요합니다. 당신의 컴파일러에 그것들이나 비슷한 것들이 없다면, 당신은 이 수준의 안전을 달성할 수 없습니다.
또한 다음 C11 기능을 사용합니다. 그러나 이전 표준을 사용하여 이 기능이 없는 경우 몇 가지 더러운 트릭을 사용하여 극복할 수 있습니다(예: C 코드에서 ":-!!"란 무엇입니까? ).
또한 다음 확장을 사용하지만 동일한 작업을 수행하는 표준 C 방식이 있습니다.
sizeof 연산자를 사용할 수 있지만 포인터 참조를 사용하기 때문에 함수에서는 작동하지 않습니다. 배열의 길이를 찾기 위해 다음을 수행할 수 있습니다.
len = sizeof(arr)/sizeof(arr[0])
원래 여기에 있는 코드: 배열의 요소 수를 찾는 C 프로그램
배열의 데이터 유형을 알고 있으면 다음과 같이 사용할 수 있습니다.
int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22}; int noofele = sizeof(arr)/sizeof(int);
또는 배열의 데이터 유형을 모르는 경우 다음과 같이 사용할 수 있습니다.
noofele = sizeof(arr)/sizeof(arr[0]);
참고: 이것은 배열이 런타임에 정의되지 않고(예: malloc) 배열이 함수로 전달되지 않은 경우에만 작동합니다. 두 경우 모두 arr
(배열 이름)은 포인터입니다.
모든 사람이 사용하는 매크로 ARRAYELEMENTCOUNT(x)
가 잘못 평가됩니다. 현실적으로 이것은 '배열' 유형을 생성하는 표현식을 가질 수 없기 때문에 민감한 문제일 뿐입니다.
/* Compile as: CL /P "macro.c" */ # define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0])) ARRAYELEMENTCOUNT(p + 1);
실제로 다음 과 같이 평가합니다.
(sizeof (p + 1) / sizeof (p + 1[0]));
반면
/* Compile as: CL /P "macro.c" */ # define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0]) ARRAYELEMENTCOUNT(p + 1);
다음과 같이 올바르게 평가됩니다.
(sizeof (p + 1) / sizeof (p + 1)[0]);
이것은 실제로 배열의 크기와 명시적으로 많은 관련이 없습니다. 나는 C 전처리기가 어떻게 작동하는지 제대로 관찰하지 못해서 많은 오류를 발견했습니다. 항상 매크로 매개변수를 래핑하고 표현식이 포함될 수 있습니다.
이것은 정확합니다. 내 예는 나쁜 예였습니다. 그러나 그것은 실제로 일어나야 하는 일입니다. 이전에 언급했듯이 p + 1
은 포인터 유형으로 종료되고 전체 매크로를 무효화합니다(포인터 매개변수가 있는 함수에서 매크로를 사용하려는 경우와 마찬가지로).
하루가 끝나면이 특정 경우에 오류가별로 중요하지 않습니다 (그래서 나는 모든 사람의 시간을 낭비하고 있습니다. 허자!). 왜냐하면 '배열'유형의 표현식이 없기 때문입니다. 그러나 실제로 전처리기 평가에 대한 요점은 미묘하다고 저는 생각합니다.
다차원 배열의 경우 조금 더 복잡합니다. 종종 사람들은 명시적 매크로 상수를 정의합니다.
#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", " " }, };
그러나 이러한 상수는 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);
이 코드는 C 및 C++에서 작동합니다. 2차원 이상의 배열의 경우 다음을 사용하십시오.
sizeof(name[0][0][0]) sizeof(name[0][0][0][0])
등, 무한대로.
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
sizeof(array) / sizeof(array[0])
"당신은 자신의 발에 총을 쏘는 미묘한 방법을 도입했습니다"
C '네이티브' 배열은 크기를 저장하지 않습니다. 따라서 배열의 길이를 별도의 변수/const에 저장하고 배열을 전달할 때마다 전달하는 것이 좋습니다.
#define MY_ARRAY_LENGTH 15 int myArray[MY_ARRAY_LENGTH];
항상 네이티브 배열을 피해야 합니다(할 수 없는 경우 제외). C++를 작성하는 경우 STL 의 '벡터' 컨테이너를 사용하십시오. "어레이와 비교하여 거의 동일한 성능을 제공합니다." 훨씬 더 유용합니다!
// 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();
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
배열을 전달하기 위해 정말로 이것을 하고 싶다면 배열을 원하는 유형에 대한 포인터와 배열의 크기를 나타내는 정수를 저장하는 구조를 구현하는 것이 좋습니다. 그런 다음 이를 함수에 전달할 수 있습니다. 해당 포인터에 배열 변수 값(첫 번째 요소에 대한 포인터)을 할당하기만 하면 됩니다. 그런 다음 Array.arr[i]
로 이동하여 i번째 요소 Array.size
를 사용하여 배열의 요소 수를 가져올 수 있습니다.
나는 당신을 위해 몇 가지 코드를 포함했습니다. 별로 유용하지는 않지만 더 많은 기능으로 확장할 수 있습니다. 솔직히 말해서 이것이 원하는 것이라면 C 사용을 중단하고 이러한 기능이 내장된 다른 언어를 사용해야 합니다.
/* 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; }
가장 좋은 방법은 이 정보를 예를 들어 다음과 같은 구조로 저장하는 것입니다.
typedef struct { int *array; int elements; } list_s;
생성, 파괴, 평등 확인 및 기타 필요한 모든 기능과 같은 필요한 모든 기능을 구현합니다. 매개변수로 전달하는 것이 더 쉽습니다.
sizeof
함수는 메모리에서 배열이 사용하는 바이트 수를 반환합니다. 배열의 요소 수를 계산하려면 해당 숫자를 배열의 sizeof
변수 유형으로 나누어야 합니다. int array[10];
, 컴퓨터의 변수 유형 정수가 32비트(또는 4바이트)인 경우 배열의 크기를 얻으려면 다음을 수행해야 합니다.
int array[10]; int sizeOfArray = sizeof(array)/sizeof(int);
&
연산자를 사용할 수 있습니다. 소스 코드는 다음과 같습니다.
#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; };
다음은 샘플 출력입니다.
1549216672 1549216712 ---- diff---- 4 The size of array a is 10
가장 간단한 답변:
#include <stdio.h> int main(void) { int a[] = {2,3,4,5,4,5,6,78,9,91,435,4,5,76,7,34};//for Example only int size; size = sizeof(a)/sizeof(a[0]);//Method printf ("size = %d",size); return 0; }
더 우아한 솔루션은
size_t size = sizeof(a) / sizeof(*a);
사전 정의된 배열의 경우:
int a[]={1,2,3,4,5,6};
배열의 요소 수 계산:
element _count =sizeof(a) / sizeof(a[0]);
이미 제공된 답변 외에도 다음을 사용하여 특별한 경우를 지적하고 싶습니다.
sizeof(a) / sizeof (a[0])
a
char
, unsigned char
또는 signed char
의 배열인 경우 이러한 유형의 피연산자가 하나인 sizeof
1
이 되기 때문에 sizeof
두 번 사용할 필요가 없습니다.
C18,6.5.3.4/4에서 인용:
"
sizeof
char
,unsigned char
또는signed char
(또는 그 정규화된 버전) 유형의 피연산자에 적용되면1
입니다."
따라서 sizeof(a) / sizeof (a[0])
a
char
, unsigned char
또는 signed char
유형의 배열인 경우 NUMBER OF ARRAY ELEMENTS / 1
과 같습니다. 1을 통한 나누기는 중복됩니다.
이 경우 간단히 줄여서 다음을 수행할 수 있습니다.
sizeof(a)
예를 들어:
char a[10]; size_t length = sizeof(a);
증거를 원하시면 여기 GodBolt에 대한 링크가 있습니다.
그럼에도 불구하고 부서는 유형이 크게 변경되는 경우(이러한 경우는 드물지만) 안전을 유지합니다.
참고: 이것은 주석에서 MM이 지적한 대로 정의되지 않은 동작을 제공할 수 있습니다.
int a[10]; int size = (*(&a+1)-a) ;
출처 : http:www.stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c
탭을 4칸으로 재정의 (0) | 2023.04.30 |
---|---|
Windows 개발 시스템을 사용하여 iPhone용으로 개발하려면 어떻게 해야 합니까? (0) | 2023.04.30 |
줄 바꿈(줄 연속)은 어떻게 합니까? (0) | 2023.04.30 |
Python이 해석되는 경우 .pyc 파일은 무엇입니까? (0) | 2023.04.30 |
Chrome을 사용하여 XML 대신 JSON을 반환하도록 ASP.NET Web API를 얻으려면 어떻게 해야 합니까? (0) | 2023.04.30 |