배열의 크기를 찾는 방법(첫 번째 요소 배열을 가리키는 포인터에서)?
먼저, 몇 가지 코드가 있습니다.
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
어레이의 크기를 확인할 수 있는 방법이 있습니까?ptr
를 가리키는 것입니까(32비트 시스템에서 4바이트인 크기를 지정하는 것이 아니라)?
아니, 그럴 수 없다.컴파일러는 포인터가 가리키는 내용을 알지 못합니다.알려진 대역 외 값으로 배열을 종료한 다음 해당 값까지 크기를 계산하는 것과 같은 요령이 있지만 이는 사용되지 않습니다.sizeof()
.
또 다른 요령은 잔이 언급한 것인데, 그것은 크기를 어딘가에 비축하는 것입니다.예를 들어, 배열을 동적으로 할당하는 경우 필요한 블록보다 한 int 더 큰 블록을 할당하고 첫 번째 int에 크기를 저장한 다음 반환합니다.ptr+1
배열에 대한 포인터로 사용합니다.크기가 필요한 경우 포인터를 줄이고 숨김 값을 확인합니다.어레이뿐만 아니라 처음부터 전체 블록을 해제해야 합니다.
대답은 "아니오"입니다.
C 프로그래머가 하는 일은 배열의 크기를 어딘가에 저장하는 것입니다.될, 도 있고, 그은구일될수있고도가부있것프로래, 수도고속약일간가머그조의,▁it,머수래있고도▁structure속▁a▁cheat,malloc()
배열 시작 전에 길이 값을 저장하기 위해 요청된 메모리보다 많습니다.
동적 어레이(malloc 또는 C++ new)의 경우 다른 사용자가 언급한 대로 어레이 크기를 저장하거나 추가, 제거, 카운트 등을 처리하는 어레이 관리자 구조를 구축해야 합니다.그러나 기본적으로 저장 중인 각 어레이 유형에 맞게 구축해야 하기 때문에 관리해야 하는 어레이 유형이 여러 개인 경우 번거롭기 때문에 C는 이 기능을 거의 C++만큼 잘 수행하지 못합니다.
예제와 같은 정적 배열의 경우 크기를 가져오는 데 사용되는 공통 매크로가 있지만 매개 변수가 실제로 정적 배열인지 확인하지 않으므로 권장하지 않습니다.매크로는 실제 코드에서 사용됩니다. 예를 들어 Linux 커널 헤더에서는 아래와 약간 다를 수 있습니다.
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
#endif
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", ARRAY_SIZE(days));
printf("%u\n", sizeof(ptr));
return 0;
}
당신은 이와 같은 매크로를 경계해야 하는 이유를 구글에 검색할 수 있습니다.조심하세요.
가능하다면 벡터와 같은 C++ 표준 dlib가 훨씬 안전하고 사용하기 쉽습니다.
()의 크기를 사용하지 않고 C++ 템플릿을 사용하는 깨끗한 솔루션이 있습니다.다음 getSize() 함수는 정적 배열의 크기를 반환합니다.
#include <cstddef>
template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
return SIZE;
}
다음은 foo_t 구조의 예입니다.
#include <cstddef>
template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
return SIZE;
}
struct foo_t {
int ball;
};
int main()
{
foo_t foos3[] = {{1},{2},{3}};
foo_t foos5[] = {{1},{2},{3},{4},{5}};
printf("%u\n", getSize(foos3));
printf("%u\n", getSize(foos5));
return 0;
}
출력:
3
5
모든 정답이 말했듯이 배열의 감쇠 포인터 값만으로는 이 정보를 얻을 수 없습니다.함수에 의해 수신된 인수가 감쇠 포인터인 경우, 원래 배열의 크기는 함수가 해당 크기를 알 수 있도록 다른 방법으로 제공되어야 합니다.
여기 지금까지 제공된 것과 다른 제안이 있습니다. 이 제안은 효과적입니다. 대신 어레이에 포인터를 전달하십시오.이 제안은 C가 템플릿이나 참조를 지원하지 않는다는 점을 제외하면 C++ 스타일 제안과 유사합니다.
#define ARRAY_SZ 10
void foo (int (*arr)[ARRAY_SZ]) {
printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr));
}
그러나 전달되는 배열의 크기를 정확하게 알 수 있도록 함수가 정의되어 있기 때문에 이 제안은 문제에 대해 다소 어리석은 것입니다(따라서 배열에서 의 크기를 사용할 필요가 거의 없습니다).하지만, 그것이 하는 일은 어떤 종류의 안전을 제공하는 것입니다.원하지 않는 크기의 배열을 전달하는 것을 금지합니다.
int x[20];
int y[10];
foo(&x); /* error */
foo(&y); /* ok */
함수가 임의의 크기의 배열에서 작동할 수 있어야 하는 경우에는 함수에 크기를 추가 정보로 제공해야 합니다.
이 특정 예제의 경우, typeef를 사용하는 경우가 있습니다(아래 참조).물론 이렇게 하면 포인터가 가리키는 것이 무엇인지 알 수 있으므로 SIZEOF_DAYS를 사용하는 것이 좋습니다.
malloc() 등에서 반환되는 (void *) 포인터가 있으면 포인터가 가리키는 데이터 구조를 확인할 수 없으므로 크기를 확인할 수 없습니다.
#include <stdio.h>
#define NUM_DAYS 5
typedef int days_t[ NUM_DAYS ];
#define SIZEOF_DAYS ( sizeof( days_t ) )
int main() {
days_t days;
days_t *ptr = &days;
printf( "SIZEOF_DAYS: %u\n", SIZEOF_DAYS );
printf( "sizeof(days): %u\n", sizeof(days) );
printf( "sizeof(*ptr): %u\n", sizeof(*ptr) );
printf( "sizeof(ptr): %u\n", sizeof(ptr) );
return 0;
}
출력:
SIZEOF_DAYS: 20
sizeof(days): 20
sizeof(*ptr): 20
sizeof(ptr): 4
마법의 해결책은 없습니다.C는 반사적인 언어가 아닙니다.물체는 자동적으로 그들이 무엇인지 알지 못합니다.
하지만 선택의 폭이 넓습니다.
- 매개 변수를 추가
- 매크로로 통화를 래핑하고 자동으로 매개 변수 추가
- 더 복잡한 개체를 사용합니다.동적 배열과 배열 크기를 포함하는 구조를 정의합니다.그런 다음 구조물의 주소를 전달합니다.
다음과 같은 작업을 수행할 수 있습니다.
int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;
이 문제에 대한 저의 해결책은 배열의 길이를 배열에 대한 메타 정보로 구조 배열에 저장하는 것입니다.
#include <stdio.h>
#include <stdlib.h>
struct Array
{
int length;
double *array;
};
typedef struct Array Array;
Array* NewArray(int length)
{
/* Allocate the memory for the struct Array */
Array *newArray = (Array*) malloc(sizeof(Array));
/* Insert only non-negative length's*/
newArray->length = (length > 0) ? length : 0;
newArray->array = (double*) malloc(length*sizeof(double));
return newArray;
}
void SetArray(Array *structure,int length,double* array)
{
structure->length = length;
structure->array = array;
}
void PrintArray(Array *structure)
{
if(structure->length > 0)
{
int i;
printf("length: %d\n", structure->length);
for (i = 0; i < structure->length; i++)
printf("%g\n", structure->array[i]);
}
else
printf("Empty Array. Length 0\n");
}
int main()
{
int i;
Array *negativeTest, *days = NewArray(5);
double moreDays[] = {1,2,3,4,5,6,7,8,9,10};
for (i = 0; i < days->length; i++)
days->array[i] = i+1;
PrintArray(days);
SetArray(days,10,moreDays);
PrintArray(days);
negativeTest = NewArray(-5);
PrintArray(negativeTest);
return 0;
}
하지만 저장할 어레이의 올바른 길이를 설정하는 데 신경을 써야 합니다. 친구들이 설명한 것처럼 이 길이를 확인할 수 있는 방법이 없기 때문입니다.
이것이 제 개인적인 코드 방식입니다.저는 제가 필요로 하는 가치를 얻을 수 있으면서도 가능한 한 단순하게 유지하는 것을 좋아합니다.
typedef struct intArr {
int size;
int* arr;
} intArr_t;
int main() {
intArr_t arr;
arr.size = 6;
arr.arr = (int*)malloc(sizeof(int) * arr.size);
for (size_t i = 0; i < arr.size; i++) {
arr.arr[i] = i * 10;
}
return 0;
}
아니요, 사용할 수 없습니다.sizeof(ptr)
배열의 크기를 찾다ptr
가 가리키고 있습니다.
길이를 추가 공간에 저장하려면 추가 메모리(어레이 크기보다 큼)를 할당하는 것이 유용합니다.
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
일 수[]는 요소 수 * 데이터 유형의 크기인 20입니다.포인터의 크기는 무엇을 가리키는지에 관계없이 4입니다.포인터가 주소를 저장하여 다른 요소를 가리키기 때문입니다.
줄에는 다음이 있습니다.'\0'
문자열의 길이가 다음과 같은 함수를 사용하여 얻을 수 있도록 끝에 있는 문자strlen
예를 들어 정수 배열의 문제는 어떤 값도 끝 값으로 사용할 수 없기 때문에 가능한 한 가지 해결책은 배열을 주소 지정하고 끝 값으로 사용하는 것입니다.NULL
포인터
#include <stdio.h>
/* the following function will produce the warning:
* ‘sizeof’ on array function parameter ‘a’ will
* return size of ‘int *’ [-Wsizeof-array-argument]
*/
void foo( int a[] )
{
printf( "%lu\n", sizeof a );
}
/* so we have to implement something else one possible
* idea is to use the NULL pointer as a control value
* the same way '\0' is used in strings but this way
* the pointer passed to a function should address pointers
* so the actual implementation of an array type will
* be a pointer to pointer
*/
typedef char * type_t; /* line 18 */
typedef type_t ** array_t;
int main( void )
{
array_t initialize( int, ... );
/* initialize an array with four values "foo", "bar", "baz", "foobar"
* if one wants to use integers rather than strings than in the typedef
* declaration at line 18 the char * type should be changed with int
* and in the format used for printing the array values
* at line 45 and 51 "%s" should be changed with "%i"
*/
array_t array = initialize( 4, "foo", "bar", "baz", "foobar" );
int size( array_t );
/* print array size */
printf( "size %i:\n", size( array ));
void aprint( char *, array_t );
/* print array values */
aprint( "%s\n", array ); /* line 45 */
type_t getval( array_t, int );
/* print an indexed value */
int i = 2;
type_t val = getval( array, i );
printf( "%i: %s\n", i, val ); /* line 51 */
void delete( array_t );
/* free some space */
delete( array );
return 0;
}
/* the output of the program should be:
* size 4:
* foo
* bar
* baz
* foobar
* 2: baz
*/
#include <stdarg.h>
#include <stdlib.h>
array_t initialize( int n, ... )
{
/* here we store the array values */
type_t *v = (type_t *) malloc( sizeof( type_t ) * n );
va_list ap;
va_start( ap, n );
int j;
for ( j = 0; j < n; j++ )
v[j] = va_arg( ap, type_t );
va_end( ap );
/* the actual array will hold the addresses of those
* values plus a NULL pointer
*/
array_t a = (array_t) malloc( sizeof( type_t *) * ( n + 1 ));
a[n] = NULL;
for ( j = 0; j < n; j++ )
a[j] = v + j;
return a;
}
int size( array_t a )
{
int n = 0;
while ( *a++ != NULL )
n++;
return n;
}
void aprint( char *fmt, array_t a )
{
while ( *a != NULL )
printf( fmt, **a++ );
}
type_t getval( array_t a, int i )
{
return *a[i];
}
void delete( array_t a )
{
free( *a );
free( a );
}
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#define array(type) struct { size_t size; type elem[0]; }
void *array_new(int esize, int ecnt)
{
size_t *a = (size_t *)malloc(esize*ecnt+sizeof(size_t));
if (a) *a = ecnt;
return a;
}
#define array_new(type, count) array_new(sizeof(type),count)
#define array_delete free
#define array_foreach(type, e, arr) \
for (type *e = (arr)->elem; e < (arr)->size + (arr)->elem; ++e)
int main(int argc, char const *argv[])
{
array(int) *iarr = array_new(int, 10);
array(float) *farr = array_new(float, 10);
array(double) *darr = array_new(double, 10);
array(char) *carr = array_new(char, 11);
for (int i = 0; i < iarr->size; ++i) {
iarr->elem[i] = i;
farr->elem[i] = i*1.0f;
darr->elem[i] = i*1.0;
carr->elem[i] = i+'0';
}
array_foreach(int, e, iarr) {
printf("%d ", *e);
}
array_foreach(float, e, farr) {
printf("%.0f ", *e);
}
array_foreach(double, e, darr) {
printf("%.0lf ", *e);
}
carr->elem[carr->size-1] = '\0';
printf("%s\n", carr->elem);
return 0;
}
#define array_size 10
struct {
int16 size;
int16 array[array_size];
int16 property1[(array_size/16)+1]
int16 property2[(array_size/16)+1]
} array1 = {array_size, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
#undef array_size
array_size가 size 변수에 전달되고 있습니다.
#define array_size 30
struct {
int16 size;
int16 array[array_size];
int16 property1[(array_size/16)+1]
int16 property2[(array_size/16)+1]
} array2 = {array_size};
#undef array_size
용도:
void main() {
int16 size = array1.size;
for (int i=0; i!=size; i++) {
array1.array[i] *= 2;
}
}
대부분의 구현에는 할당된 개체의 예약된 크기를 알려주는 기능이 있습니다.malloc()
또는calloc()
예를 들어 GNU는malloc_usable_size()
그러나 이렇게 하면 역방향 블록의 크기가 반환되며, 이 크기는 다음 값보다 클 수 있습니다.malloc()
/realloc()
.
배열에 있는 요소의 수를 찾기 위해 정의할 수 있는 널리 사용되는 매크로가 있습니다(Microsoft CRT는 OOB에도 이름을 제공합니다)._countof
):
#define countof(x) (sizeof(x)/sizeof((x)[0]))
그러면 다음과 같이 쓸 수 있습니다.
int my_array[] = { ... some elements ... };
printf("%zu", countof(my_array)); // 'z' is correct type specifier for size_t
언급URL : https://stackoverflow.com/questions/492384/how-to-find-the-size-of-an-array-from-a-pointer-pointing-to-the-first-element-a
'programing' 카테고리의 다른 글
jQuery 또는 플레인 자바스크립트를 사용하여 URL 매개 변수를 가져오는 방법은 무엇입니까? (0) | 2023.05.09 |
---|---|
엑셀에서 달력 주를 날짜로 변환하려면 어떻게 해야 합니까? (0) | 2023.05.09 |
전체 ASP에 대해 브라우저 캐시를 비활성화합니다.NET 웹사이트 (0) | 2023.05.04 |
명령줄을 통해 OS X에서 간단한 Hello World 프로그램 컴파일 (0) | 2023.05.04 |
업데이트 색인 실행 취소 --assume-unchanged (0) | 2023.05.04 |