programing

C 포인터에서 어레이 크기를 가져오려면 어떻게 해야 합니까?

goodsources 2022. 8. 30. 22:31
반응형

C 포인터에서 어레이 크기를 가져오려면 어떻게 해야 합니까?

'배열을 '배열'로 .mystructn음음음같 뭇매하다

if (NULL == (p = calloc(sizeof(struct mystruct) * n,1))) {
 /* handle error */
}

할 수 건 나, later, have, have, 나, later밖에 요.p더.np

그럴 수도 있을 것 같아요free(p)알고 있습니다.malloc()할당되어 있는 메모리의 양을 추적하고 있기 때문에 길이를 알 수 있습니다.이정 문의 의의 의? ?? ???★★★★★★★★★★★★。

int length = askMallocLibraryHowMuchMemoryWasAlloced(p) / sizeof(mystruct)

를 하면 알 수 .n★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★♪은은생 각각?

이 하려면 , 「 」의 실장 에 크게 합니다. 이 정보를 얻으려면 다음 구현 세부사항을 크게 의존해야 합니다.malloc히,는malloc는 사용자가 요구하는 것보다 더 많은 바이트를 할당할 수 있습니다(특정 메모리아키텍처에서의 효율화 등).코드를 재설계하는 것이 훨씬 더 나을 것이다.n명쾌하게그 대안은 적어도 같은 정도의 재설계와 훨씬 더 위험한 접근법입니다(비표준적이고 포인터의 의미를 남용하여 다음 사용자에게 유지보수의 악몽이 될 수 있습니다). : 길이 저장n주소에 .malloc'd로 합니다.을 사용하다

void *p = calloc(sizeof(struct mystruct) * n + sizeof(unsigned long int),1));
*((unsigned long int*)p) = n;

n is is is is is at at at at at at at at at at at at at에 저장됩니다.*((unsigned long int*)p)은 지금이다.

void *arr = p+sizeof(unsigned long int);

편집: 악마의 옹호자 역할을 하기 위해...이러한 「솔루션」이 모두 재설계를 필요로 하는 것은 알고 있습니다만, 실천해 봅시다.물론 위에 제시된 솔루션은 (충분한) 구조의 진부한 구현일 뿐입니다.다음과 같이 정의할 수 있습니다.

typedef struct { 
  unsigned int n;
  void *arr;
} arrInfo;

arrInfopointers.raw가 입니다.

이제 요리하는 거야.하지만 재설계를 하는 한 왜 여기서 멈출까요?당신이 정말로 원하는 것은 ADT(Abstract Data Type)입니다.알고리즘 및 데이터 구조 클래스의 도입 텍스트가 있으면 이 작업을 수행할 수 있습니다.ADT는 데이터 유형의 공용 인터페이스를 정의하지만 해당 데이터 유형의 구현을 숨깁니다.따라서 어레이의 ADT는 일반적으로 다음과 같이 보일 수 있습니다.

typedef void* arrayInfo;
(arrayInfo)newArrayInfo(unsignd int n, unsigned int itemSize);
(void)deleteArrayInfo(arrayInfo);
(unsigned int)arrayLength(arrayInfo);
(void*)arrayPtr(arrayInfo);
...

지향 에 거의 해 있는 , 스트레이트 C.사용하여 오브젝트 을 할 수 . C++ 컴파일러를 하는 것이 .std::vector.

여기서 C에 대한 간단한 질문을 받고 C++에 도달했습니다.하느님이 우리 모두를 도와 주시길.

어레이 크기를 직접 추적합니다.free는 malloc 체인을 사용하여 할당된 블록을 해방합니다.이 블록의 크기가 반드시 요청된 어레이와 같을 필요는 없습니다.

이전 답변을 확인하기 위해:포인터를 조사하는 것만으로 이 포인터를 반환한 malloc에 의해 할당된 메모리의 양을 알 수 있는 방법은 없습니다.

효과가 있었다면?

이것이 불가능한 이유의 한 가지 예입니다.포인터에 할당된 메모리를 반환하는 get_size(void *)라고 하는 가설 함수를 가진 코드를 상상해 보겠습니다.

typedef struct MyStructTag
{ /* etc. */ } MyStruct ;

void doSomething(MyStruct * p)
{
   /* well... extract the memory allocated? */
   size_t i = get_size(p) ;
   initializeMyStructArray(p, i) ;
}

void doSomethingElse()
{
   MyStruct * s = malloc(sizeof(MyStruct) * 10) ; /* Allocate 10 items */
   doSomething(s) ;
}

그게 먹혀들어도 왜 안 먹힐까?

하지만 이 접근법의 문제는 C에서는 포인터 산술로 게임을 할 수 있다는 것입니다.doSomethingElse()를 다시 쓰겠습니다.

void doSomethingElse()
{
   MyStruct * s = malloc(sizeof(MyStruct) * 10) ; /* Allocate 10 items */
   MyStruct * s2 = s + 5 ; /* s2 points to the 5th item */
   doSomething(s2) ; /* Oops */
}

함수에 유효한 포인터를 보냈지만 malloc에 의해 반환된 포인터는 전송되지 않았기 때문에 get_size가 어떻게 동작해야 하는지.또한 get_size가 크기를 찾는 데 많은 어려움을 겪었더라도(즉, 비효율적인 방법으로), 이 경우 컨텍스트에서 잘못된 값이 반환됩니다.

결론

이 문제를 회피하는 방법은 항상 있습니다.또, C 에서는, 항상 독자적인 할당기를 쓸 수 있습니다만, 할당되어 있는 메모리의 양을 기억하는 것만으로 문제가 되는 경우도 있습니다.

일부 컴파일러는 msize() 또는 이와 유사한 함수(_msize() 등)를 제공합니다.

끔찍한 방법을 추천해도 될까요?

다음과 같이 모든 어레이를 할당합니다.

void *blockOfMem = malloc(sizeof(mystruct)*n + sizeof(int));

((int *)blockofMem)[0] = n;
mystruct *structs = (mystruct *)(((int *)blockOfMem) + 1);

러 always then then then음음음음음음음음음음음 then then then then then then then then then then then then then then then 。int *1번째 요소에 접속합니다.

해 주세요.free이 포인터는 어레이 포인터 자체가 아닙니다!

또한, 이것은 여러분이 머리카락을 쥐어뜯게 만드는 끔찍한 벌레들을 야기할 것입니다.API 호출이나 뭐 그런 걸로 할당 펑크를 정리할 수 있을 것 같아요.

malloc은 적어도 당신이 요청한 만큼 큰 메모리 블록을 반환할 것입니다.따라서 블록 크기를 쿼리해도 어레이 크기를 확실하게 알 수 없습니다.따라서 코드를 수정하여 직접 추적하면 됩니다.

포인터 배열에는 NULL 종단 배열을 사용할 수 있습니다.그 후, 스트링을 사용한 것과 같이 길이를 결정할 수 있습니다.이 예에서는 구조 속성을 사용하여 종료 표시를 할 수 있습니다.물론 이는 NULL일 수 없는 멤버가 있는지 여부에 따라 달라집니다.그러면 어레이 내의 모든 구조체에 대해 설정되어야 하는 속성 이름이 있다고 가정하고 크기를 조회할 수 있습니다.


int size;
struct mystruct *cur;

for (cur = myarray; cur->name != NULL; cur++)
    ;

size = cur - myarray;

그런데 이 예에서는 calloc(n, sizeof(구조 신비주의))가 되어야 합니다.

사람들은 c c pointers의 에 했다.stdlib.h실실의 malloc()일부 구현에서는 요청된 크기보다 클 수 있는 할당된 블록 크기를 반환하는 확장 기능을 제공합니다.

동작이 필요한 경우 전용 메모리 할당기를 사용하거나 쓸 수 있습니다.가장 간단한 방법은 랩퍼의 설치입니다.stdlib.h 들면과 같습니다.예를 들어 다음과 같습니다.

void* my_malloc(size_t s);     /* Calls malloc(s), and if successful stores 
                                  (p,s) in a list of handled blocks */
void my_free(void* p);         /* Removes list entry and calls free(p) */
size_t my_block_size(void* p); /* Looks up p, and returns the stored size */
...

"malloc'd(또는 calloc'd) 데이터 블록의 크기를 알 수 있습니까?"라는 질문입니다.그리고 다른 사람들이 말했듯이, 표준적인 방법으로는 아니다.

단, 이를 실현하는 커스텀 malloc 구현이 있습니다.예를 들어 http://dmalloc.com/

방법은 모르겠지만, 말록의 내부를 뒤지는 건 좋지 않은 생각일 것 같아요

할당한 메모리 크기를 저장할 수 없는 이유는 무엇입니까?

편집: 코드를 수정해야 한다는 것을 알고 있다면 n, 음, 그렇게 하십시오.네, malloc을 폴링하는 것은 빠르고 쉬울 수 있지만 n을 알면 혼란을 최소화하고 디자인을 강화할 수 있습니다.

malloc 라이브러리에 블록의 크기를 물어볼 수 없는 이유 중 하나는 할당자가 보통 최소 세분화 요건(예를 들어 16바이트)을 충족하기 위해 요청 크기를 반올림하기 때문입니다.따라서 5바이트를 요청하면 16사이즈 블록을 돌려받을 수 있습니다.16을 5로 나누면 1개만 할당하면 3개의 요소가 나옵니다.malloc 라이브러리가 처음에 요구한 바이트 수를 추적하려면 추가 공간이 필요하므로 사용자가 직접 추적하는 것이 가장 좋습니다.

이건 내 일상의 시험이야.7개의 변수를 설정하여 부동값을 유지한 후 최대값을 찾는 데 사용되는 배열에 할당합니다.

마술은 myMax 호출에 있습니다.

float mmax = myMax((float *)&arr, (int) size of(arr)/size of(arr[0]));

그리고 그건 마법 같았죠, 안 그래요?

myMax는 플로트 어레이 포인터(플로트*)를 상정하고 있기 때문에 &ar를 사용하여 어레이의 주소를 취득하여 플로트 포인터로 캐스팅합니다.

또한 myMax는 어레이 내의 요소 수를 int로 예상합니다.이 값은 sizeof()를 사용하여 배열의 바이트 크기와 배열의 첫 번째 요소를 지정한 후 총 바이트 수를 각 요소의 바이트 수로 나눕니다.(일부 시스템에서는 2바이트, OS X Mac에서는 4바이트이며 다른 시스템에서는 다른 것일 수 있기 때문에 int의 크기를 추측하거나 하드코드로 구분해서는 안 됩니다).

참고:데이터에 샘플 수가 다를 수 있는 경우 이 모든 것이 중요합니다.

테스트 코드는 다음과 같습니다.

#include <stdio.h>

float a, b, c, d, e, f, g;

float myMax(float *apa,int soa){
 int i;
 float max = apa[0];
 for(i=0; i< soa; i++){
  if (apa[i]>max){max=apa[i];}
  printf("on i=%d val is %0.2f max is %0.2f, soa=%d\n",i,apa[i],max,soa);
 }
 return max;
}

int main(void)
{
 a = 2.0;
 b = 1.0;
 c = 4.0;
 d = 3.0;
 e = 7.0;
 f = 9.0;
 g = 5.0;
 float arr[] = {a,b,c,d,e,f,g};

 float mmax = myMax((float *)&arr,(int) sizeof(arr)/sizeof(arr[0]));
 printf("mmax = %0.2f\n",mmax);

 return 0;
}

uClibc에는MALLOC_SIZE의 매크로:

/* The size of a malloc allocation is stored in a size_t word
   MALLOC_HEADER_SIZE bytes prior to the start address of the allocation:

     +--------+---------+-------------------+
     | SIZE   |(unused) | allocation  ...   |
     +--------+---------+-------------------+
     ^ BASE             ^ ADDR
     ^ ADDR - MALLOC_HEADER_SIZE
*/

/* The amount of extra space used by the malloc header.  */
#define MALLOC_HEADER_SIZE          \
  (MALLOC_ALIGNMENT < sizeof (size_t)       \
   ? sizeof (size_t)                \
   : MALLOC_ALIGNMENT)

/* Set up the malloc header, and return the user address of a malloc block. */
#define MALLOC_SETUP(base, size)  \
  (MALLOC_SET_SIZE (base, size), (void *)((char *)base + MALLOC_HEADER_SIZE))
/* Set the size of a malloc allocation, given the base address.  */
#define MALLOC_SET_SIZE(base, size) (*(size_t *)(base) = (size))

/* Return base-address of a malloc allocation, given the user address.  */
#define MALLOC_BASE(addr)   ((void *)((char *)addr - MALLOC_HEADER_SIZE))
/* Return the size of a malloc allocation, given the user address. */
#define MALLOC_SIZE(addr)   (*(size_t *)MALLOC_BASE(addr))

malloc()는 공간 할당에 관한 메타데이터를 실제로 할당된 공간으로부터8 바이트 전에 저장합니다.이를 사용하여 버퍼 공간을 결정할 수 있습니다.x86-64의 됩니다.따라서 할당된 공간이 16의 배수(대부분의 경우)인 경우 다음과 같이 사용할 수 있습니다.

코드

#include <stdio.h>
#include <malloc.h>

int size_of_buff(void *buff) {
        return ( *( ( int * ) buff - 2 ) - 17 ); // 32 bit system: ( *( ( int * ) buff - 1 ) - 17 )
}

void main() {
        char *buff = malloc(1024);
        printf("Size of Buffer: %d\n", size_of_buff(buff));
}

산출량

Size of Buffer: 1024

언급URL : https://stackoverflow.com/questions/232691/how-can-i-get-the-size-of-an-array-from-a-pointer-in-c

반응형