programing

calloc(4, 6)는 calloc(6, 4)와 동일합니까?

minimums 2023. 6. 17. 08:56
반응형

calloc(4, 6)는 calloc(6, 4)와 동일합니까?

저는 초보 C 프로그래머이고, 저는 이것이 그럴 것이라고 생각했지만, 가능하다면 확인하고 싶습니다.

만약 그들이 같다면, 대신에 하나의 주장을 채택하는 것이 어떨까요?

사이에 실질적인 차이는 없습니다.calloc(a, b)그리고.calloc(b, a)그럼에도 불구하고 - 둘 다 동일한 양의 공간을 할당하고 적절하게 채웁니다.블록 내 요소의 정렬은 입력되지 않으며, 물건의 "크기"가 무엇인지 명시적으로 말하고 있기 때문에 패딩이 필요하지 않습니다(모든 패딩은 사용하여 제어됩니다).sizeof두 번째 변론에서

사용하는 이유와 관련하여callocmalloc사람들은 종종 정해진 숫자의 항목에 공간을 할당하기 위해 할당 루틴을 사용합니다.calloc()를 적절하게 지정할 수 있습니다.예를 들어, 100개의 정수 또는 20개의 자체 구조에 대한 공간이 필요한 경우:

int *pInt = calloc (100, sizeof(int));
tMyStruct *pMyStruct = calloc (20, sizeof(tMyStruct));

이 코드는 실제로 동등한 코드보다 약간 "더 좋아" 보입니다.malloc() 전화 번호:

int *pInt = malloc (100 * sizeof(int));
tMyStruct *pMyStruct = malloc (20 * sizeof(tMyStruct));

하지만 노련한 C 코더들에게는 (물론 제로 초기화 외에는) 실질적인 구별이 없습니다.

저는 야생에서 캘록을 사용해 본 적이 없다고 말해야 합니다. 왜냐하면 저는 거의 항상 칼록을 만들기 때문입니다.struct0이 말이 안 되는 곳에서.원하는 값을 얻기 위해 모든 필드를 수동으로 초기화하는 것을 선호합니다.

게시된 훌륭한 답변에, 저는 사용하는 것과 다른 점을 하나 더 추가하고 싶습니다.calloc(nelem, elsize)malloc(nelem * elsize)『 』 『 』의 calloc만약 당신이nelem그리고.elsize할당이 수. 한 함 곱 충 컸 때 정 히 분 만 크 것 순 기 작 가 한 럼 할 진 처 은 것 실 유 당 을 보 니 입 다 다 기 할 는 패 하 발 께 다 면 큼 할 킬 으 버 일 수 플 로 를 오 ▁a ▁were ▁rather ▁fail ation ▁alloc ▁enough ,malloc호출할 것입니다.

이 기능만으로도 제가 선호하는 것으로 충분할 것 같습니다.callocmalloc배경 판독.

calloc(4, 6)와 calloc(6, 4)는 같지 않습니다.

일반적인 32비트/64비트 시스템에서 첫 번째 시스템은 32바이트를 할당하고 두 번째 시스템은 24바이트를 할당합니다.


void *calloc(size_t nelem, size_t elsize);

핵심은 calloc이 배열로 올바르게 정렬된 것처럼 메모리를 반환해야 한다는 것입니다.배열을 할당하고 다음과 같이 사용합니다.

A *p = (A*)calloc(count, sizeof(A));
for (int i = 0; i < count; ++i)
{
    f(&(p[i]));
    // f(p + i) is also valid
}

또는

A *p = (A*)calloc(count, sizeof(A));
for (A *q = p; q != p + count; ++q)
{
    f(q);
}

calloc은 대상 시스템의 패딩 및 기타 운영 요구 사항을 고려하여 어레이를 할당해야 합니다.따라서 6바이트 구조를 8바이트로 패딩해야 하는 대부분의 32비트 시스템에서는 8바이트의 4 로트를 할당합니다.

첫 번째 인수가 ()의 크기인 calloc은 버그일 가능성이 높으며 조사되어야 합니다.

두 번째 인수가 (유형)의 크기가 아닌 calloc은 정의되지 않았습니다.그것은 숨겨진 추측의 냄새가 나고 항구에 위험합니다.

명확화:일반적인 32비트/64비트 시스템에서는 구조가 패딩되고 32비트의 배수에 맞춰 정렬될 가능성이 높습니다.이 시스템에서는 크기가 6바이트를 반환하지 않습니다.사실 컴파일러/플랫폼이 필요로 하는 것이라면 컴파일러가 16바이트의 배수로 패딩하고 정렬하지 않는다는 보장은 없습니다.

제 대답은 구조물의 크기에 대한 가정을 해서는 안 된다는 사실에 근거한 것입니다.컴파일러 옵션 또는 대상 플랫폼에 따라 변경할 수 있습니다.단지 당신의 두 번째 주장이 표현의 크기인지 확인하고 추측을 하지 마세요.


표준에서:

calloc() 함수는 각각의 크기가 elsize인 nelem 요소 배열에 대해 사용되지 않은 공간을 할당해야 합니다.공간은 모든 비트 0으로 초기화되어야 합니다.

할당이 성공할 경우 반환되는 포인터는 모든 유형의 객체에 대한 포인터에 할당된 다음 할당된 공간에서 (공간이 명시적으로 해방되거나 재할당될 때까지) 해당 객체 또는 객체 배열에 액세스하는 데 사용될 수 있도록 적절하게 정렬되어야 합니다.각각의 이러한 할당은 다른 객체와 분리된 객체에 대한 포인터를 생성해야 합니다.반환된 포인터는 할당된 공간의 시작(가장 낮은 바이트 주소)을 가리켜야 합니다.

(제가 옳다고 생각하는) 승인된 답변에도 불구하고 정렬로 인해 할당된 바이트 수에 대한 혼란이 있는 것 같습니다.여기 gcc-4를 사용한 32비트 리눅스에 대한 작은 테스트가 있습니다.3:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  char* p1 = calloc(6, 4);
  char* p2 = calloc(4, 6);
  char* p3 = calloc(1,1);
  printf("%p, %p, %p\n", p1, p2, p3);
  return 0;
}

결과는 다음과 같습니다.

0x826b008, 0x826b028, 0x826b048

는 그은둘다 둘 다를 .calloc(6,4)그리고.calloc(4,6)시스템에서 32바이트로 반올림된 동일한 양의 메모리를 할당합니다.다음으로 숫자 변경하기calloc(3,4)그리고.calloc(4,3)를 제공합니다.

0x95d2008, 0x95d2018, 0x95d2028

이는 12개가 요청되고 프로그램에 할당될 때 16바이트가 예약됨을 나타냅니다. 모두 느어경든우, 다둘다 모두calloc(a,b)그리고.calloc(b,a)호출은 메모리 사용량에 동일한 영향을 미칩니다.


300자로는 충분하지 않기 때문에 조나단 레플러가 추가했습니다.

이 프로그램을 생각해 보세요. 메모리가 진짜 체처럼 새지만 다음과 같은 점을 보여줍니다.

#include <stdlib.h>
#include <stdio.h>

int main()
{
    int i, j, k;

    for (i = 1; i < 17; i++)
        for (j = 1; j < 9; j++)
            for (k = 0; k < 4; k++)
                printf("(%2d,%d)%d: %p\n", i, j, k, calloc(i, j));
    return(0);
}

윈도우즈의 Cygwin에서는 16바이트 간격의 블록을 할당하는 것으로 시작합니다(실제로 두 번째 블록은 첫 번째 블록 뒤에 24바이트이지만 이후에는 16바이트 간격입니다).(2,7) 할당 시 블록 주소가 24바이트씩 증가하기 시작합니다. 마찬가지로 (3,4) 블록을 16바이트씩 할당하지만 (3,5) 블록을 24바이트씩 할당합니다.또한 레코드의 경우 (4,6) 및 (6,4) 모두 포인터를 32바이트 간격으로 반환합니다.

이는 할당 호출과 관련된 일부 오버헤드가 있음을 보여줍니다.K&R에서 malloc() 등의 전형적인 구현을 보면 블록의 크기가 사용할 자격이 있는 메모리보다 먼저 저장된다는 것을 알 수 있습니다.구현 방식에 따라 이러한 작업이 달라집니다. 메모리 짓밟기를 걱정하는 사람들은 사용자가 혼란을 일으킬 수 있는 곳 근처에 제어 데이터를 저장하는 것을 피할 수 있습니다.

oc(4,6)를 호출하면 24바이트의 데이터에 대한 신뢰할 수 있는 액세스 권한만 갖게 됩니다.구현 시 32바이트의 반환 값이 제공되더라도 요청한 24바이트 이상을 안전하게 사용할 수 없습니다.그리고 당신이 요청한 범위를 벗어나면 malloc()의 디버깅 버전이 관찰됩니다.

약간의 차이가 있습니다. Calloc은 필요할 때만 메모리를 0으로 만들기로 결정할 수 있습니다. 그러면 요소의 크기를 알 수 있는 이점이 있습니다.

이를 수행하는 어떤 구현체도 이름을 댈 수 없지만, 이를 위해 고안되었습니다.

예를 들어,

하나는 4GB의 메모리를 호출하지만 시스템은 2GB만 가지고 있습니다. 가상 메모리에 0을 2GB 쓰는 것은 의미가 없기 때문에 시스템은 메모리에 로드될 때 메모리를 0으로 만들기 위해 이 메모리에 더티 플래그를 설정할 수 있습니다.

이 질문을 조사할 수 있는 다른 방법이 있습니다.

GNU C 라이브러리는 다음과 같이 calloc를 정의합니다.

void * __libc_calloc (size_t n, size_t elem_size)
{
  // ... (declarations)

  /* size_t is unsigned so the behavior on overflow is defined.  */
  bytes = n * elem_size;
#define HALF_INTERNAL_SIZE_T \
  (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
  if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0))
    {
      if (elem_size != 0 && bytes / elem_size != n)
        {
          __set_errno (ENOMEM);
          return 0;
        }
    }

  void *(*hook) (size_t, const void *) = atomic_forced_read (__malloc_hook);
  if (__builtin_expect (hook != NULL, 0))
    {
      sz = bytes;
      mem = (*hook)(sz, RETURN_ADDRESS (0));
      if (mem == 0)
        return 0;

      return memset (mem, 0, sz);
    }

  sz = bytes;

  // ...more stuff, but no mention of n & elem_size anymore
}

그래서 적어도 glibc에서 이 두 통화는 동일한 효과를 가집니다.

똑같습니다.그 이유는 대부분의 시간을 당신이 사용하기를 원하기 때문입니다.sizeof연산자를 인수 중 하나로 지정합니다.두 개의 매개 변수를 전달하는 것이 번거로우시다면, 전화하세요.malloc()하나의 주장을 가지고 있습니다.

언급URL : https://stackoverflow.com/questions/501839/is-calloc4-6-the-same-as-calloc6-4

반응형