답변:
행정상 개요 :
int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
전체 답변 :
바이트 단위로 배열의 크기를 결정하려면 sizeof
연산자를 사용할 수 있습니다 .
int a[17];
size_t n = sizeof(a);
내 컴퓨터에서 ints의 길이는 4 바이트이므로 n은 68입니다.
배열의 요소 수를 결정하기 위해 배열의 전체 크기를 배열 요소의 크기로 나눌 수 있습니다. 다음과 같이 유형 으로이 작업을 수행 할 수 있습니다.
int a[17];
size_t n = sizeof(a) / sizeof(int);
정답을 얻으십시오 (68/4 = 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);
ARRAYSIZE
정의 된 마크로가 있습니다 WinNT.h
(다른 헤더에 의해 가져옴). 따라서 WinAPI 사용자는 자신의 마크로를 정의 할 필요가 없습니다.
static int a[20];
. 그러나 귀하의 의견은 배열과 포인터의 차이를 인식하지 못하는 독자에게 유용합니다.
sizeof
방법은 올바른 방법입니다 IFF 는 매개 변수로받지 배열을 다루고있다. 함수에 매개 변수로 전송 된 배열은 포인터로 취급되므로 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
length of parameter:2
첫 번째 배열 요소에 대한 포인터 만 전달된다면?
(sizeof array / sizeof *array)
.
sizeof
포인터로 소멸 된 배열 값을 처리 할 때 도움 이 되지 않는다는 점은 주목할 가치가 있습니다. 배열의 시작을 가리 키더라도 컴파일러의 경우 해당 배열의 단일 요소에 대한 포인터와 같습니다 . 포인터는 배열을 초기화하는 데 사용 된 배열에 대해 다른 것을 "기억"하지 않습니다.
int a[10];
int* p = a;
assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
char
32 비트의 C를 가졌음을 기억합니다 . 모든 표준에 따르면 0에서 127 사이의 정수 값을 나타낼 수 있으며 범위는 -127에서 127까지 (char는 부호 있음) 또는 0에서 255는 (char는 부호 없음)입니다.
"속임수"의 크기는 내가 아는 가장 좋은 방법이며, 괄호 사용에있어 작은 (하지만 나에게는 이것이 주요 애완 동물)이다.
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);
이제 당신은 보호됩니다. 물론 변수의 이름을 복제하지만 변수를 변경하면 컴파일러가 감지 할 수있는 방식으로 침입 할 가능성이 높습니다.
sizeof(int)
보다 적은 지시가 필요 합니까 sizeof(foo)
?
int x = 1+1;
대 생각하십시오 int x = (1+1);
. 여기서 괄호는 순전히 미적입니다.
sizeof
C ++ 및 C89에서 항상 일정합니다. C99의 가변 길이 배열을 사용하면 런타임에 평가할 수 있습니다.
sizeof
연산자 일 수 있지만 Linus Torvalds에 따라 함수로 취급해야합니다. 동의한다. 그의 합리적인 설명을 여기에서 읽으십시오 : lkml.org/lkml/2012/7/11/103
int size = (&arr)[1] - arr;
설명을 보려면 이 링크 를 확인하십시오.
ptrdiff_t
입니다. 일반적으로 64 비트 시스템에서는이 유형이보다 큽니다 int
. 변경하더라도 int
에 ptrdiff_t
이 코드에 있다면, 그것은 여전히 버그가 arr
주소 공간의 절반 이상을 차지한다.
/3G
옵션을 사용하면 3G / 1G 사용자 / 커널 분할이 가능하여 주소 공간 크기의 최대 75 %까지 배열 크기를 가질 수 있습니다.
foo buf1[80]; foo buf2[sizeof buf1/sizeof buf1[0]]; foo buf3[(&buf1)[1] - buf1];
전역 변수로 고려하십시오 . 상수가 buf3[]
아니므로 선언이 실패 (&buf1)[1] - buf1
합니다.
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
(배열 이름)은 포인터입니다.
int noofele = sizeof(arr)/sizeof(int);
코딩보다 절반 정도 더 좋습니다 int noofele = 9;
. 를 사용 sizeof(arr)
하면 어레이 크기가 변경 될 때 유연성이 유지됩니다. 그러나 변경 sizeof(int)
유형에 arr[]
따라 업데이트가 필요합니다 . 더 나은 사용하는 sizeof(arr)/sizeof(arr[0])
유형이 잘 알려진 경우에도 마찬가지입니다. 사용하는 이유는 불분명 int
위한 noofele
대 size_t
, 유형에 의해 반환 sizeof()
.
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
포인터 유형으로 끝나고 전체 매크로를 무효화합니다 (포인터 매개 변수가있는 함수에서 매크로를 사용하려는 것처럼).
하루가 끝날 때,이 특별한 경우, 결함은 실제로 중요하지 않습니다 (따라서 모든 사람의 시간을 낭비하고 있습니다. huzzah!). 그러나 전 처리기 평가에 대한 요점은 미묘하다고 생각합니다.
(sizeof (x) / sizeof (*x))
있습니까?
대한 다차원 배열 은 조금 더 복잡하다. 종종 사람들은 명시적인 매크로 상수를 정의합니다.
#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 ++에서 작동합니다. 차원이 3 이상인 어레이의 경우
sizeof(name[0][0][0])
sizeof(name[0][0][0][0])
등, 광고 인피니 엄.
sizeof(array) / sizeof(array[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
size_t size_of_element
아직 int
함께 int n = sizeof (a) / sizeof (a[0]);
하지size_t n = sizeof (a) / sizeof (a[0]);
char a[INT_MAX + 1u];
경우 int n
에는 사용 int n = sizeof (a) / sizeof (a[0]);
되지 않습니다 (UB). 사용 size_t n = sizeof (a) / sizeof (a[0]);
하면이 문제가 발생하지 않습니다.
sizeof
배열의 두 가지 다른 크기 중 하나를 요소 수 또는 바이트 단위로 가져 오는 데 사용 하지 않는 것이 좋습니다 . 두 가지 크기 각각에 대해 아래 표시된 매크로를 사용하여보다 안전하게 만들 수 있습니다. 이유는 명백한 테이너에 대한 코드의 의도와 차이를 확인하는 것입니다 sizeof(ptr)
에서 sizeof(arr)
첫눈에 버그가 다음 모든 사람들이 코드를 읽기위한 명백하다 그래서 (이 방법을 쓴 명확하지 않다).
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)[0]) * ARRAY_SIZE(arr))
must_be_array(arr)
-Wsizeof-pointer-div
버그가있는 그대로 필요합니다 (4/2/2 기준) :
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a) (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a) _Static_assert(is_array(a), "Not a `[]` !")
#define must_be_array(a) ( \
0 * (int)sizeof( \
struct { \
Static_assert_array(a); \
char ISO_C_forbids_a_struct_with_no_members__; \
} \
) \
)
이 주제와 관련하여 중요한 버그가있었습니다 : 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))
작동 방식은 매우 간단합니다. 분열을 취소 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]))
안전하게 만들고 싶습니다. C11 _Static_assert()
및 일부 GCC 확장 이 필요 합니다 : Expressions의 선언 및 선언 , __builtin_types_compatible_p :
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a) (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a) _Static_assert(is_array(a), "Not a `[]` !")
#define ARRAY_SIZE(arr) ( \
{ \
Static_assert_array(arr); \
sizeof(arr) / sizeof((arr)[0]); \
} \
)
이제는 ARRAY_SIZE()
완전히 안전하므로 모든 파생 상품이 안전합니다.
__arraycount()
다음을 제공합니다 .Libbsd 는 에 괄호가 없기 때문에 안전하지 않은 매크로 __arraycount()
를 제공 <sys/cdefs.h>
하지만 괄호를 직접 추가 할 수 있으므로 헤더에 나눗셈을 쓸 필요조차 없습니다 (이미 존재하는 코드를 복제하는 이유는 무엇입니까? ). 이 매크로는 시스템 헤더에 정의되어 있으므로이를 사용하면 위의 매크로를 사용해야합니다.
#include <sys/cdefs.h>
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a) (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a) _Static_assert(is_array(a), "Not a `[]` !")
#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))
일부 시스템 nitems()
은 <sys/param.h>
대신 제공 하고 일부 시스템은 둘 다 제공합니다. 시스템을 점검하고 보유한 시스템을 사용해야하며 이식성을 위해 일부 전 처리기 조건을 사용하고 둘 다 지원해야합니다.
불행하게도 ({})
gcc 확장자는 파일 범위에서 사용할 수 없습니다. 파일 범위에서 매크로를 사용하려면 정적 어설 션이 내부에 있어야합니다 sizeof(struct {})
. 그런 다음 0
결과에 영향을 미치지 않도록 곱하십시오 . 캐스트 (int)
는 리턴하는 함수를 시뮬레이트하는 데 좋을 수 있습니다 (int)0
(이 경우 필요하지 않지만 다른 경우에는 재사용 할 수 있음).
#include <sys/cdefs.h>
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a) (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a) _Static_assert(is_array(a), "Not a `[]` !")
#define must_be_array(a) ( \
0 * (int)sizeof( \
struct { \
Static_assert_array(a); \
char ISO_C_forbids_a_struct_with_no_members__; \
} \
) \
)
#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)[0]) * ARRAY_SIZE(arr))
sizeof(arr)
다른 곳에 표시되지 않은 안전하지 않은 일반적인 구성 ( )에 대한 솔루션을 보여줍니다 ARRAY_BYTES(arr)
.
sizeof
않고 대신이 구성을 사용하는 것입니다. 매번 이러한 구성을 작성하고 싶을 경우, 실수를하게 될 것입니다 (붙여 넣기하면 매우 일반적이며, 괄호가 많기 때문에 매번 작성하면 매우 일반적 임) ...
sizeof
은 분명히 안전하지 않으며 (이유는 대답에 있습니다) 매크로를 사용하지 않고 매번 제공 한 구조를 사용하는 것이 더 안전하지 않으므로 갈 수있는 유일한 방법입니다 매크로입니다.
"발에 몸을 쏘는 미묘한 방법을 소개했습니다"
C '기본'배열은 크기를 저장하지 않습니다. 따라서 배열의 길이를 별도의 변수 / 상수로 저장하고 배열을 전달할 때마다 전달하는 것이 좋습니다.
#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();
enum
입니다.
#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;
}
strcpy(d.name, name);
오버플로를 처리 하지 않고 코드를 공표 할 수 없습니다 .
가장 좋은 방법은이 정보를 예를 들어 구조에 저장하는 것입니다.
typedef struct {
int *array;
int elements;
} list_s;
작성, 파괴, 평등 점검 및 기타 필요한 모든 기능을 구현하십시오. 매개 변수로 전달하는 것이 더 쉽습니다.
int elements
대 이유가 size_t elements
무엇입니까?
&
연산자 를 사용할 수 있습니다 . 소스 코드는 다음과 같습니다.
#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
ptrdiff_t
. sizeof()
결과 size_t
. C는 어느 것이 더 넓거나 더 높거나 같은지 정의 하지 않습니다 . 따라서 몫의 유형이 ((char *)(&a+1)-(char *)a)/(sizeof(a[0]))
확실하지 size_t
않으므로 인쇄 z
하면 UB 가 발생할 수 있습니다. 간단히 사용 printf("The size of array a is %zu\n", sizeof a/sizeof a[0]);
하면 충분합니다.
(char *)(&a+1)-(char *)a
는 상수가 아니며 고정 크기로도 런타임에 계산 될 수 있습니다 a[10]
. sizeof(a)/sizeof(a[0])
이 경우 컴파일 타임에 일정하게 수행됩니다.
이미 제공된 답변 외에도 다음을 사용하여 특별한 경우를 지적하고 싶습니다.
sizeof(a) / sizeof (a[0])
경우 a
하나의 배열입니다 char
, unsigned char
또는 signed char
당신은 사용할 필요가 없습니다 sizeof
이후 두 번 sizeof
항상에 결과를 않는 이러한 유형의 하나의 피연산자로 표현 1
.
C18,6.5.3.4 / 4에서 인용 :
" 경우
sizeof
형 갖는 오퍼랜드에인가되는char
,unsigned char
또는signed char
(또는 이들의 정규화 된 버전) 결과이다1
."
따라서 if 가 , 또는 의 유형의 배열 인 경우 sizeof(a) / sizeof (a[0])
와 같습니다 . 1을 통한 나누기는 중복됩니다.NUMBER OF ARRAY ELEMENTS / 1
a
char
unsigned char
signed char
이 경우 간단히 축약하고 수행 할 수 있습니다.
sizeof(a)
예를 들면 다음과 같습니다.
char a[10];
size_t length = sizeof(a);
증거를 원한다면 여기에 GodBolt 링크가 있습니다 .
그럼에도 불구하고 부서는 유형이 크게 변경되면 안전을 유지합니다 (이 경우는 드물지만).
참고 : 이것은 주석에서 MM이 지적한대로 정의되지 않은 동작을 제공 할 수 있습니다.
int a[10];
int size = (*(&a+1)-a) ;
*
연산자는 과거 - 더 - 끝 포인터에 적용되지 않을 수 있습니다
*(&a+1) - a;
에서 다른 (&a)[1] - a;
두, 위의하지 *(&a+1)
와는 (&a)[1]
끝을지나 1로 계산?
x[y]
다음과 같이 정의됩니다.*(x + (y))