1

I have this code.

   int x[5];
   printf("%d\n",sizeof(x) );


   int *a;
   a = new int[3];
   printf("%d\n",sizeof(*a));

When I pass a 'static' array to sizeof(), it returns the dimension of the declared array multiplied by the number of bytes that the datatype uses in memory. However, a dynamic array seems to be different. My question is what should I do to get the size of an 'dynamic' array?

PD: Could it be related to the following?

int *a;
a=new int[3];
a[0]=3;
a[1]=4;
a[2]=5;
a[3]=6;

Why can I modify the third position if it's supposed I put a 'limit' in "a=new int[3]".

loguepw
  • 35
  • 1
  • 6
  • 4
    There is no standard (i.e. portable) way to determine the size of a dynamically-allocated array after it's been allocated. If you'd like to do something like that, try using `std::vector` - it knows its own size and doesn't suffer from some of the weirdnesses that come up with arrays and pointers in C++. – templatetypedef Sep 10 '14 at 01:47
  • You should be using `std::cout` rather than `printf`, specifically for the reason that you are using the wrong format specifier. `sizeof` gives you a `size_t`, and you're telling `printf` that you're giving it an `int`, so any output you get is the result of undefined behaviour. – dreamlax Sep 10 '14 at 01:56

3 Answers3

4

When I pass a 'static' array to sizeof(), it returns the dimension of the declared array multiplied by the number of bytes that the datatype uses in memory.

Correct, that is how the size of the entire array is computed.

However, a dynamic array seems to be different.

This is because you are not passing a dynamic array; you are passing a pointer. Pointer is a data type with the size independent of the size of the block of memory to which it may point, hence you always get a constant value. When you allocate memory for your dynamically sized memory block, you need to store the size of allocation for future reference:

size_t count = 123; // <<== You can compute this count dynamically
int *array = new int[count];
cout << "Array size: " << (sizeof(*array) * count) << endl;

C++14 will have variable-length arrays. These arrays will provide a proper size when you check sizeof.

Could it be related to the following? [...]

No, it is unrelated. Your code snippet shows undefined behavior (writing past the end of the allocated block of memory), meaning that your code is invalid. It could crash right away, lead to a crash later on, or exhibit other arbitrary behavior.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

In C++ arrays do not have any intrinsic size at runtime.

At compile time one can use sizeof as you showed in order to obtain the size known to the compiler, but if the actual size is not known until runtime then it is the responsibility of the program to keep track of the length.

Two popular strategies are:

  • Keep a separate variable that contains the current length of the array.
  • Add an extra element to the end of the array that contains some sort of marker value that indicates that it's the last element. For example, if your array is known to be only of positive integers then you could use -1 as your marker.

If you do not keep track of the end of your array and you write beyond what you allocated then you risk overwriting other data stored adjacent to the array in memory, which could cause crashes or other undefined behavior.

Other languages tend to use the former strategy and provide a mechanism for obtaining the current record of the length. Some languages also allow the array to be dynamically resized after it's created, which usually involves creating a new array and copying over all of the data before destroying the original.

The vector type in the standard library provides an abstraction over arrays that can be more convenient when the size of the data is not known until runtime. It keeps track of the current array size, and allows the array to grow later. For example:

#include <vector>

int main() {
    std::vector<int> a;
    a.push_back(3);
    a.push_back(4);
    a.push_back(5);
    a.push_back(6);
    printf("%d\n", a.size());

    return 0;
}

As a side-note, since a.size() (and sizeof(...)) returns a size_t, which isn't necessarily the same size as an int (though it happens to be on some platforms), using printf with %d is not portable. Instead, one can use iostream, which is also more idiomatic C++:

#include <iostream>

std::cout << a.size() << '\n';
Martin Atkins
  • 62,420
  • 8
  • 120
  • 138
  • The first line of your example doesn't do what you think it does. Also, in C++ one should typically avoid the C I/O functions and use C++ streams instead, e.g. `std::cout`. – dreamlax Sep 10 '14 at 01:54
  • Right you are. I originally wrote it as a ``new`` and then thought better of it and rewrote it as an automatic, but didn't clean up my mess. – Martin Atkins Sep 10 '14 at 01:58
  • Used ``printf`` because the requester used it in his question and didn't want to confuse the issue by potentially introducing two new concepts in one example. But yes, agreed that one would usually not use ``printf`` in C++. – Martin Atkins Sep 10 '14 at 02:01
0

You do not, at least not in standard C++. You have to keep track of it yourself, use an alternative to raw pointers such as std::vector that keeps track of the allocated size for you, or use a non-standard function such as _msize https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/msize?view=msvc-160 on Microsoft Windows or malloc_size https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/malloc_size.3.html on MacOS X.

drescherjm
  • 10,365
  • 5
  • 44
  • 64
Benilda Key
  • 2,836
  • 1
  • 22
  • 34