'size of'(어레이를 가리키는 포인터)를 찾는 방법
먼저, 몇 가지 코드를 다음에 나타냅니다.
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()
또 다른 방법은 잔이 말한 크기로 어딘가에 보관하는 것입니다.예를 들어 어레이를 동적으로 할당하는 경우 필요한 블록보다 1int 큰 블록을 할당하고 첫 번째 int에 크기를 저장한 후 반환합니다.ptr+1
배열에 대한 포인터로 사용합니다.크기가 필요한 경우 포인터를 줄이고 저장된 값을 살펴봅니다.어레이뿐만 아니라 블록 전체를 처음부터 해제해야 합니다.
대답은 "아니오"입니다.
C 프로그래머가 하는 일은 배열의 크기를 어딘가에 저장하는 것입니다.도 있습니다.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++ stdlib을 사용합니다.
모든 정답이 언급했듯이 어레이의 손상된 포인터 값만으로는 이 정보를 얻을 수 없습니다.붕괴된 포인터가 함수에 의해 수신된 인수인 경우 함수가 그 크기를 알 수 있도록 원래 배열의 크기를 다른 방법으로 제공해야 합니다.
여기에서는 지금까지의 제안과는 다른 제안을 제시합니다.대신 포인터를 어레이에 건네주세요.이 제안은 C가 템플릿 또는 참조를 지원하지 않는다는 점을 제외하고는 C++ 스타일의 제안과 유사합니다.
#define ARRAY_SZ 10
void foo (int (*arr)[ARRAY_SZ]) {
printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr));
}
다만, 전달되는 어레이의 사이즈를 정확하게 알 수 있도록 함수가 정의되어 있기 때문에, 이 제안은 고객님의 문제에는 다소 우스운 것입니다(따라서 어레이에서는 size of을 사용할 필요가 없습니다).하지만, 그것이 하는 일은 일종의 안전성을 제공하는 것이다.불필요한 크기의 배열을 통과하지 못하게 됩니다.
int x[20];
int y[10];
foo(&x); /* error */
foo(&y); /* ok */
이 함수가 임의의 크기의 어레이로 동작할 수 있도록 되어 있는 경우는, 그 함수의 사이즈를 추가 정보로 제공할 필요가 있습니다.
다음과 같은 작업을 수행할 수 있습니다.
int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;
에는 '아까운'이 .'\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;
}
sizeof()를 사용하지 않고 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는 반사적인 언어가 아니다.사물은 자신이 무엇인지 자동으로 알지 못합니다.
하지만 선택의 여지가 많습니다.
- 당연히 파라미터를 추가합니다.
- 콜을 매크로로 랩하여 자동으로 파라미터를 추가합니다.
- 좀 더 복잡한 개체를 사용합니다.동적 배열과 배열 크기를 포함하는 구조를 정의합니다.그런 다음 구조체의 주소를 전달합니다.
내 코드로 내가 개인적으로 이렇게 하는 거야.필요한 가치를 얻을 수 있을 때 가능한 한 심플하게 하고 싶습니다.
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;
}
이 문제의 해결 방법은 어레이의 길이를 어레이에 대한 메타 정보로 구조체 어레이에 저장하는 것입니다.
#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;
}
그러나 저장하려는 어레이의 올바른 길이를 설정하는 데 신경을 써야 합니다. 이는 이 길이를 확인하는 방법이 아니기 때문입니다. 이는 당사의 친구들이 자세히 설명했듯이 말입니다.
안 요, 안 돼요.sizeof(ptr)
배열의 크기를 구하다ptr
를 가리키고 있습니다.
여분의 메모리(어레이 크기보다 큰 메모리)를 할당하는 것은, 여분의 공간에 길이를 보존하는 경우에 도움이 됩니다.
#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가 크기 변수로 전달되고 있습니다.
#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;
}
}
이 예에서는 typedef를 사용하는 경우(아래 참조)가 있습니다.물론 이렇게 하면 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
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입니다.포인터가 다른 요소의 주소를 저장하여 해당 요소를 가리키기 때문입니다.
대부분의 구현에는 할당된 개체의 예약된 크기를 알려주는 기능이 있습니다.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-sizeof-a-pointer-pointing-to-an-array
'programing' 카테고리의 다른 글
Firebase 오류: "Unknown field filter op" (알 수 없는 필드 필터 op)이 표시된다. (0) | 2022.08.17 |
---|---|
Vuetify 아이콘 크기 (0) | 2022.08.17 |
Concurrent Hash Map과 Collections의 차이점은 무엇입니까?synchronized Map(맵)? (0) | 2022.08.17 |
ES6 vuex Import 파일과 Import(내포된 Import) (0) | 2022.08.17 |
Vue 컴포넌트의 메서드에서 소품 값을 변경할 수 있습니까? (0) | 2022.08.17 |