'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 |