프로그래밍 방식으로 C ++ 배열의 크기를 결정합니까?
이 질문은 비슷한 질문에서 영감을 얻었습니다. delete []는 피연산자 배열의 크기를 어떻게 "알 수 있습니까?"
내 질문은 약간 다릅니다. 프로그래밍 방식으로 C ++ 배열의 크기를 결정하는 방법이 있습니까? 그렇지 않다면 왜? 배열을 취하는 모든 함수에는 크기를 지정하기 위해 정수 매개 변수가 필요합니다. 그러나 연결된 질문에서 지적했듯이 delete[]
할당 해제 할 메모리의 크기를 알아야합니다.
다음 C ++ 코드를 고려하십시오.
int* arr = new int[256];
printf("Size of arr: %d\n", sizeof(arr));
이것은 Size of arr: 4
단지 포인터의 크기 인 " "를 인쇄합니다 . 256을 인쇄하는 기능이 있으면 좋겠지 만 C ++에는 존재하지 않는다고 생각합니다. (다시 질문의 일부는 왜 존재하지 않는지입니다.)
설명 : 힙 (즉 " int arr[256];
") 대신 스택에 배열을 선언 하면 sizeof
연산자가 1024 (배열 길이 * sizeof (int))를 반환 한다는 것을 알고 있습니다.
delete []
할당 된 크기를 알고 있습니다. 그러나 이러한 지식은 런타임 또는 운영 체제의 메모리 관리자에 있으므로 컴파일 중에 컴파일러에서 사용할 수 없습니다. 그리고 sizeof()
실제 함수가 아니며 컴파일러에 의해 실제로 상수로 평가됩니다. 이는 컴파일 중에 크기를 알 수없는 동적 할당 배열에 대해 수행 할 수없는 작업입니다.
또한 다음 예를 고려하십시오.
int *arr = new int[256];
int *p = &arr[100];
printf("Size: %d\n", sizeof(p));
컴파일러는 크기가 무엇인지 어떻게 알 수 p
있습니까? 문제의 근원은 C와 C ++의 배열이 일류 객체가 아니라는 것입니다. 그것들은 포인터로 쇠퇴하고, 컴파일러 나 프로그램 자체가 포인터가에 의해 할당 된 메모리 청크의 시작을 가리키는 지 new
, 단일 객체 또는 청크의 중간 위치를 가리키는 지 알 수있는 방법이 없습니다. 에서 할당 한 메모리의 new
.
그 이유 중 하나는 C와 C ++가 메모리 관리를 프로그래머와 운영 체제에 맡기고 있기 때문에 가비지 수집이없는 이유이기도합니다. 구현 new
및 delete
C ++가 매우 다른 방식으로 자신의 메모리를 관리 할 수 있습니다 다양한 플랫폼에 사용하기위한 것입니다 때문에 C ++ 표준의 일부가 아닙니다. 최신 Intel CPU에서 실행되는 Windows 상자 용 워드 프로세서를 작성하는 경우 C ++에서 할당 된 모든 배열과 해당 크기를 추적하도록 할 수 있지만 DSP.
아니요, 표준 C ++에서는이를 수행 할 수있는 방법이 없습니다.
내가 알지 못하는 정말 좋은 이유가 없습니다. 아마도 크기는 구현 세부 사항으로 간주되었으며 노출되지 않는 것이 가장 좋습니다. 주 당신이 malloc에가 (1000), 반환 된 블록이 그것의 것만 --- 1000 바이트임을 보증은 없다 말할 때 적어도 1000 바이트. 대부분 약 1020 (오버 헤드에 대해 1K에서 4 바이트를 뺀 값)입니다. 이 경우 "1020"크기는 런타임 라이브러리가 기억해야 할 중요한 크기입니다. 물론 이는 구현간에 변경 될 것입니다.
이것이 표준위원회가 정확한 크기를 추적하는 std : vector <>를 추가 한 이유입니다.
실제로 크기를 결정하는 방법이 있지만 "안전"하지 않고 컴파일러마다 다를 수 있으므로 전혀 사용해서는 안됩니다 .
당신이 할 때 : int * arr = new int [256];
256은 관련이 없습니다.이 경우 1024를 가정하면 256 * sizeof (int)가 주어집니다.이 값은 아마도 (arr-4)에 저장됩니다.
따라서 "항목"의 수를
int * p_iToSize = arr-4;
printf ( "항목 수 % d", * p_iToSize / sizeof (int));
모든 malloc, new, 수신 한 연속 메모리 블록 이전에 무엇이든, 주어진 메모리 블록에 관한 정보로 예약 된 공간도 할당됩니다.
이를 처리하는 일반적인 방법은 벡터를 사용하는 것입니다.
int main()
{
std::vector<int> v(256);
printf("size of v is %i capacity is %i\n", sizeof(int) * v.size(), sizeof(int) * v.capacity());
}
또는 크기를 미리 정의하십시오
const int arrSize = 256;
int main()
{
int array[arrSize];
printf("Size of array is %i", sizeof(int) * arrSize);
}
C ++는 typesafe malloc을 수행하기 위해 new를 추가하기로 결정했습니다. new는 ctor를 호출하는 요소의 크기 e 수를 모두 알아야하므로 dtor를 호출하려면 삭제하십시오. 초기에는 새 개체에 전달한 개체의 번호를 삭제하기 위해 실제로 전달해야합니다.
string* p = new string[5];
delete[5] p;
그러나 그들은 new <type> []을 사용하면 숫자의 오버 헤드가 적다고 생각했습니다. 그래서 그들은 new [n]이 n을 기억하고 그것을 삭제하도록 전달해야한다고 결정했습니다. 이를 구현하는 세 가지 주요 방법이 있습니다.
- 크기에 대한 포인터의 해시 테이블 유지
- 벡터 근처에 직접 썼습니다.
- 완전히 다른 일을하다
아마도 다음과 같은 크기를 얻을 수 있습니다.
size_t* p = new size_t[10];
cout << p[-1] << endl;
// Or
cout << p[11] << endl;
아니면 그 누구도.
애플리케이션에 따라 어레이 끝에 "센티널 값"을 생성 할 수 있습니다.
센티넬 값에는 고유 한 속성이 있어야합니다.
그런 다음 센티넬 값에 대한 배열을 처리하거나 선형 검색을 수행 할 수 있습니다. 센티넬 값에 도달하면 배열 수를 갖게됩니다.
간단한 C 문자열의 경우 종료 \ 0은 센티넬 값의 예입니다.
마술 :
template <typename T, size_t S>
inline
size_t array_size(const T (&v)[S])
{
return S;
}
그리고 이것이 우리가 C ++ 11에서하는 방법입니다.
template<typename T, size_t S>
constexpr
auto array_size(const T (&)[S]) -> size_t
{
return S;
}
That's because your variable arr is only a pointer. It holds the address of a particular location in memory, without knowing anything about it. You declare it to be int*, which gives the compiler some indication of what to do when you increment the pointer. Other than that, you could be pointing into the beginning or the end of the array or into the stack or into invalid memory. But I agree with you, not being able to call sizeof is very annoying :)
QuantumPete
There is no portable way of determining the size of a dynamically-allocated array in C++ given only its pointer. C++ is made to be very flexible and to give power to the user. For example, the standard does not define how memory allocators must work, e.g. by adding a required size header. Not requiring a header allows for a lot more flexibility.
As one example, consider a string implemented as a char * array. It's common to use pointers into the middle of the array to pick out substrings. As an example, see the strtok function in the standard C library. If some header were required to be embedded just before each array, you'd need to trash portions of the array before the substring.
An alternative way to handle the headers would be to have array headers in one block of memory and have them point to the raw array memory elsewhere. In many situations, this would require two pointer lookups for each reference, which would be a big drag on performance. There are ways of overcoming these deficiencies, but they add complexity and reduce implementation flexibility.
The std::vector template is my favorite way of keeping the size of an array bound to the array itself.
C is portable assembly language with a better syntax.
Unfortunately, this is not possible. In C and C++, it is the responsibility of the programmer to remember of the length of an array since array length is not stored anywhere. Delete[] and free() does remember the size of the allocated block but they might allocate more memory than requested so their internal data structures storing the sizes of allocated memory blocks might not give you the exact size of the your array.
Note that C++ STL vectors, which are basically arrays wrapped in a class with some helper functions, do store the length of the array so if you really need this functionality, you could just use vectors.
In general, no. Arrays in C and C++ are just blocks of memory with no bookkeeping information attached. Without storing the length of the array in memory, and adding overhead to do so, it is impossible in the general case.
There is an exception for arrays that are statically allocated. For instance, if you declare: int a[50]
then sizeof(a)
will work. This is possible because the [50] is part of the static type of the array: it is known to the compiler. sizeof is interpreted at compile time.
However, if you create a pointer: int *p = a
, then sizeof(p)
will return the size of the pointer as you mention, not the size of the array, because the compiler does not know what p points to.
You can't, fundamentally:
void foo(int* arr);
int arr[100] = {0};
foo(arr+1); // Calls foo with a pointer to 100-1 elements.
A C++ array is nothing more than a collection of objects which are stored in a contiguous memory region. Since there are no holes betweeen them (padding is inside objects), you can find the next element of an array by simply incerementing the pointer. At CPU level, this is a simple adjustment. C++ only inserts a sizeof(element) multiplier.
Note that implementations may choose to implement "fat pointers" which contain array bounds. They'd need to be twice as big, as you'd need to link to some kind of "array bound descriptor". As a side effect, on such implementations you could be able to call delete [] (1+new int[5]);
No, there isn't any way to do this, you have to keep track of how big it is externally. Classes like std::vector
do this for you.
Now there is std::array, an efficient compile-time wrapper around a constant-size array:
#include <array>
int main (int argc, char** argv)
{
std::array<int, 256> arr;
printf("Size of arr: %ld\n", arr.size());
}
The parameters are <type, #elements>
.
You also get a few other niceties, like iterators, empty(), and max_size().
The compiler can't know that
char *ar = new char[100]
is an array of 100 characters because it doesn't create an actual array in memory it just creates a pointer to 100 uninitialized bytes in memory.
If you want to know the size of the given array just use std::vector. std::vector is a better array simply.
Is there any way to determine the size of a C++ array programmatically? And if not, why?
- No, unless you keep track of it yourself.
- Because if the compiler doesn't have to tell anyone besides itself about that information it constrains the compiler less. Whether that is desirable or not is up to debate.
@Dima,
How would the compiler know what the size of p is?
The compiler has to know the size of p; otherwise, it cannot implement delete[]
. The compiler doesn't need to tell anyone else how it figures that out.
For a fun way to verify this, compare the pointer returned by operator new[]
to the pointer returned by new[]
.
When you create array pointers (Create wrapper with template to pointers) you can't but when you create array of object, You can get the size of the array like that:
char* chars=new char[100];
printf("%d",*((int*)chars-1));
The delete[]
function need to deconstruct all the objects in it. to do it the new[]
keyword puts the number of elements behind all of the array.
The body of array is like that:
int count;
ObjectType* data; //This value is returned when using new[]
the way I do that is by dividing the size of the array by the size of the first element
int intarray[100];
printf ("Size of the array %d\n", (sizeof(intarray) / sizeof(intarray[0]));
It prints 100
You could just create an extra element of the array and then apply the most unlikely number that will be stored in the array. Then you can determine the number of elements through some function by passing that number.
In the case of declaring and initializing an array at the moment of creation, you can then scan it and then generate a number that does not match any of the elements of the array. But if you then modify one of the elements, you will not know if that element stores the same value as the last element, so you will then have to generate a new number to store in the last element.. Going through all that, you might as well just store the total number of elements at the moment of creation in a variable. And that will probably be the case if you only use the array within a function.
참고URL : https://stackoverflow.com/questions/197839/determine-the-size-of-a-c-array-programmatically
'IT Share you' 카테고리의 다른 글
Proxyquire, rewire, SandboxedModule 및 Sinon : 장단점 (0) | 2020.11.30 |
---|---|
Swift에서 두 사전을 어떻게 비교합니까? (0) | 2020.11.30 |
Rails 애플리케이션의 Javascript Include Tag 모범 사례 (0) | 2020.11.30 |
Java MessageFormat에서 중괄호를 이스케이프 할 수 있습니까? (0) | 2020.11.30 |
LINES 및 COLUMNS 환경 변수가 스크립트에서 손실 됨 (0) | 2020.11.30 |