code

C에 배열의 길이를 돌려주는 표준 함수가 있습니까?

starcafe 2023. 10. 10. 20:46
반응형

C에 배열의 길이를 돌려주는 표준 함수가 있습니까?

C에 배열의 길이를 돌려주는 표준 함수가 있습니까?

종종 다른 답변에서 설명된 기술은 눈에 쉽게 보이게 하기 위해 매크로에 캡슐화됩니다.다음과 같은 경우:

#define COUNT_OF( arr) (sizeof(arr)/sizeof(0[arr]))

는 인덱스 (') 합니다에 합니다.[]0가 C++됩니다를 과 함께 에서 매크로를 됩니다.operator[]()을 할 컴파일러는 나쁜 결과를 주는 대신 불평을 할 것입니다.

그러나 배열 대신 포인터를 전달할 경우 매크로가 자동으로 나쁜 결과를 제공합니다. 이것이 이 기법을 사용할 때 발생하는 주요 문제 중 하나입니다.

저는 최근 Google Chrome의 코드베이스에서 훔쳐온 더 복잡한 버전을 사용하기 시작했습니다.

#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))

이 버전에서는 포인터가 인수로 잘못 전달된 경우 컴파일러가 불만을 제기할 수 있습니다. 특히 포인터의 크기가 포인터가 가리키는 개체의 크기로 균등하게 나누어지지 않는 경우입니다.그런 상황에서 0으로 나누면 컴파일러가 오류를 범하게 됩니다.실제로 제가 사용한 컴파일러 중 적어도 한 개는 오류 대신 경고를 줍니다. 0으로 나눗셈이 있는 식에 대해 무엇을 생성하는지 잘 모르겠습니다.

저 매크로는 잘못 사용할 때 문을 닫지는 않지만, C 직선에서 본 것처럼 가깝습니다.

C++에서 작업할 때 더욱 안전한 솔루션을 원한다면 Microsoft에서 사용하는 다소 복잡한 템플릿 기반 방법을 설명하는 매크로를 사용하지 않고 Complete time size of_array를 살펴보십시오.winnt.h.

아뇨, 없습니다.

인 트릭인 를 할 수 .sizeof(array) / sizeof(array[0])이 .-합니다.
sizeof(array)합니다.sizeof(array[0])첫 번째 요소의 크기를 제공합니다.
매크로로 포장하는 방법에 대한 마이클스의 답변을 보십시오.

동적으로 할당된 배열의 경우 적분형으로 크기를 추적하거나 가능한 경우 0-종료로 만듭니다(즉, 요소를 1개 더 할당하고 마지막 요소를 0으로 설정).

sizeof array / sizeof array[0]

x다음을 통해 얻을 수 있습니다.

sizeof(x)/sizeof(x[0])

함수로 전달될 때 배열은 크기 정보를 전달하지 않는 포인터로 분해된다는 것을 알아야 합니다.실제로 크기 정보는 컴파일 시간에 계산되기 때문에 런타임에 사용할 수 없지만 어레이가 보이는 곳에서(즉, 저하되지 않은 곳에서) 사용 가능한 것처럼 동작할 수 있습니다.

어레이를 어레이로 취급해야 하는 함수에 전달할 때는 항상 두 가지 인수를 전달해야 합니다.

  • 배열의 길이,
  • 배열의 포인터.

따라서 어레이는 선언된 어레이로 취급될 수 있지만, 다른 모든 곳에서는 크기 및 포인터로 취급됩니다.

나는 다음과 같은 코드를 가지고 있는 경향이 있습니다.

#define countof(x) (sizeof(x)/sizeof(x[0]))
: : :
int numbers[10];
a = fn (countof(numbers),numbers);

그리고나서fn()사용 가능한 크기 정보를 가지고 있습니다.

제가 과거에 사용했던 또 다른 트릭(제 생각에는 조금 더 혼란스럽지만 완성도를 위해 여기에 제공하겠습니다)은 조합의 배열을 가지고 첫 번째 요소를 길이로 만드는 것입니다. 예를 들어 다음과 같습니다.

typedef union {
    int len;
    float number;
} tNumber;
tNumber number[10];
: : :
number[0].len = 5;
a = fn (number);

그리고나서fn()길이와 모든 요소에 액세스할 수 있으며 배열/pointer 이분법에 대해 걱정할 필요가 없습니다.

이를 통해 길이가 달라질 수 있는 추가적인 이점이 있습니다(즉, 할당된 장치의 수가 아니라 사용 중인 요소의 수).하지만 저는 2개의 논법 배열 버전(크기와 데이터)이 더 낫다고 생각하기 때문에 더 이상 이것을 사용하지 않는 편입니다.

배열 크기를 반환하지만 포인터에 사용하면 컴파일러 오류가 발생하는 매크로를 만들었습니다.그러나 gcc 확장에 의존한다는 점에 유의하십시오.이 때문에 휴대용 솔루션이 아닙니다.

#define COUNT(a) (__builtin_choose_expr( \
                  __builtin_types_compatible_p(typeof(a), typeof(&(a)[0])), \
                  (void)0, \
                  (sizeof(a)/sizeof((a)[0]))))

int main(void)
{
    int arr[5];
    int *p;
    int x = COUNT(arr);
//  int y = COUNT(p);
}

가(가)됩니다.error: void value not ignored as it ought to be

물론 간단한 대답은 아니오입니다.하지만 실질적인 답은 "어쨌든 알아야 한다"고 하니 이 문제를 해결하기 위한 방법을 논의해 봅시다.

는 번 언급한 수 있는 한 sizeof():

int i[] = {0, 1, 2};
...
size_t i_len = sizeof(i) / sizeof(i[0]);

이 하려고 할 가 있습니다i다로 i 그렇다면 보다 일반적인 솔루션은 어떻습니까?

일반적으로 허용되는 솔루션은 배열 길이를 배열과 함께 함수에 전달하는 것입니다.이는 표준 라이브러리에서 자주 볼 수 있습니다.

void *memcpy(void *s1, void *s2, size_t n);

윌카피n에서 바이트 수s1로.s2, 우리가 사용할 수 있게 해주는n우리의 버퍼가 넘쳐나지 않도록 하기 위해서입니다.이것은 좋은 전략입니다 - 그것은 낮은 오버헤드를 가지고 있고, 실제로 약간의 효율적인 코드를 생성합니다 (에 비해).strcpy(), 문자열의 끝을 확인해야 하고 몇 번의 반복을 해야 하는지 "knowing"할 방법이 없고 혼란스러웠습니다.strncpy(), 둘 다 확인해야 합니다 - 둘 다 더 느려질 수 있고 둘 중 하나는 사용함으로써 속도를 높일 수 있습니다.memcpy()어떤 이유에서인지 문자열의 길이를 이미 계산한 경우).

다른 접근법은 당신의 코드를 a에 캡슐화하는 것입니다.struct. 일반적인 해킹은 다음과 같습니다.

typedef struct _arr {
  size_t len;
  int arr[0];
} arr;

If we want an array of length 5, we do this:

arr *a = malloc(sizeof(*a) + sizeof(int) * 5);
a->len = 5;

하지만 이것은 적당히 잘 정의된 해킹입니다. (C99를 사용하면int arr[]다소 노동집약적입니다.이를 위한 "더 잘 정의된" 방법은 다음과 같습니다.

typedef struct _arr {
  size_t len;
  int *arr;
} arr;

But then our allocations (and deallocations) become much more complicated. The benefit of either of these approaches is, of course, that now arrays you make will carry around their lengths with them. It's slightly less memory-efficient, but it's quite safe. If you chose one of these paths, be sure to write helper functions so that you don't have to manually allocate and deallocate (and work with) these structures.

물건이 있는 경우a배열 유형의, 배열에 있는 요소의 수는 다음과 같이 표현될 수 있습니다.sizeof a / sizeof *a. 배열 개체가 포인터 유형으로 붕괴되도록 허용한 경우(또는 처음부터 포인터 개체만 있었던 경우), 일반적으로 배열에 포함된 요소의 수를 확인할 수는 없습니다.

ReferenceURL : https://stackoverflow.com/questions/1598773/is-there-a-standard-function-in-c-that-would-return-the-length-of-an-array

반응형