This question already has answers here:
What is array to pointer decay?
(11 answers)
Closed 4 years ago.
So I've been searching on Stackoverflow for all the code that can find the size of a pointer to an array. I couldn't find it.
int main() {
int array[] = {6,3, 4, 6, 2};
int *sizes = array;
cout << sizeof(sizes); // output is 8
}
Using sizeof doesn't work. Can anyone suggest a good solution? Thanks a lot!
**EDIT:
I want to find the size of the array using the pointer "sizes". I know how to find the size using the "array" variable
You can read in c++ doc http://www.cplusplus.com/reference/array/array/size/
For example:
// array::size
#include <iostream>
#include <array>
int main ()
{
std::array<int,5> myints;
std::cout << "size of myints: " << myints.size() << std::endl;
std::cout << "sizeof(myints): " << sizeof(myints) << std::endl;
return 0;
}
If you want C level answer, why did you tag this question as c++?
int main() {
int array[] = {6,3, 4, 6, 2};
cout << sizeof(array) / sizeof(int);
return 0;
}
It might not be satisfy but it's impossible to find the array's size using a pointer to the array. Pointer unlike the array, can point to any type of variable with the right casting. It doesn't store a straight memory allocation places like the array. That's why you'll always get 8 bytes in 64bit OS architecture or 4 bytes in 32bit OS architecture of size when you do sizeof(pointer).
Read about the differences between pointers and arrays in c.
Within the scope that array was declared in, sizeof(array) is the number of bytes in the array.¹
If you want the number of elements in array, that’s (sizeof(array)/sizeof(array[0])).
Since sizes is declared as an int*, sizeof(sizes) is the size of a pointer. That will be 8 for a 64-bit program, 4 for a 32-bit program, or some other size on an unusual architecture.
There is one other wrinkle: if you pass array to a function, such as:
int* reverse_array( int a[], const size_t n )
{
assert( sizeof(a) == sizeof(int*) );
// ...
}
Then the array parameter, a, automatically degrades to a pointer, and the compiler forgets its actual size. This is for backward-compatibility with C.
To use an array within another function, you must pass the size as a separate parameter, in this case n, or use a type such as std::array<int>, std::vector<int>, or a struct. The latter is what Bjarne Stroustrup’s C++ guidelines recommend, although, if you use a STL template in the ABI of a library, you are introducing a dependency on a particular implementation of the STL.
¹ Since this community loves language-lawyering: some historical C compilers measured sizes in increments other than bytes. Some C++ compiler hypothetically might make char more than 8 bits wide (although not less!) and claim to be technically conforming to the standard. You don’t need to worry about that possibility right now. Seriously, you don’t.
Related
This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Why a const size is needed in an array?
(1 answer)
Closed 4 months ago.
I want to convert a float vector to a float array in C++ 20. I searched online and found this solution:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> input({ 1, 2, 3, 4, 5 });
int arr[input.size()];
std::copy(input.begin(), input.end(), arr);
for (int i: arr) {
std::cout << i << ' ';
}
return 0;
}
But when I try to implement it, the compiler gives me an error saying that what's inside the brackets in the array declaration must be a constant expression.
Since when is this the case? I swear I've declared arrays in a similar manner in C++ before and it worked. And if you look online you'll see that everyone does this too, the example I posted seems to be the standard solution to my problem. So why does it give me an error?
Since when is this the case?
Since always. In standard C++, you cannot allocate a block of memory on the stack if you don't know its size at compile time.
Some compilers allow it as an extension. It's also standard in C99, and these arrays are then known as variable-length array.
A lot of what you see online is non standard. Just because someone does something that works for them doesn't mean it will work for you. In this case, it can certainly work for you if you don't care about writing cross-platform, standard compliant code. But if you want to write standard compliant code, you have basically two choices: make an array with a large enough size, known at compile time, and only use part of it, or don't use an array.
To address your comment:
Because a third party function (OpenGL) requires an array as an argument.
No function requires an array as argument. It can require a raw block of memory, but then you also need to give it the size of that block. You can easily do that with a std::vector, using the methods data() and size().
The only way I know of to require an array as argument is through some template magic:
template<std::size_t N>
void print_size(int (&array)[N]) {
std::cout << N;
}
Demo
Even then, you can apparently pass it a vector if you specify the size (might be undefined behavior):
std::vector<int> v = {1, 2, 3};
print_size<3>(reinterpret_cast<int(&)[3]>(*v.data()));
I'm playing with a function to get used to some C++ syntax.
Now I think, I might have misunderstood:
I'm writing to a static (?) array I had defined as myArray[0] for experimenting.
So it seems NOT to be static, but sizeof(myArray) always returns 0 (?)
but I can find mem address for each item (while I have no idea, how to get the number of items this way).
The other thing I don't understand, is why I can write myInt = myFloat?
So, what IS a static array? And should I better use <vector> for an array of undefined length?
(You could find the whole code here int2bin main.cpp)
#include <iostream>
//#include <regex>
int main()
{
while(true) {
//VARS
unsigned int arrBin[0], intNum; //working, if set [0]! NOT static???
unsigned int *pArr0 = &arrBin[0];
unsigned int *pArr1 = &arrBin[1];
std::cout << sizeof(arrBin) << '\n'; // 0 => sizeof() here items and not mem space?
std::cout << pArr0 << '\n';// 0x7fff12de6c38
std::cout << pArr1 << '\n';// 0x7fff12de6c3c
int i;
float refNum;
std::cout << "\n\nEnter a number to convert: ";
// GET INPUT
std::cin >> refNum; // float
intNum = refNum; // get int of the dec for comparing. Why does this "int = float" work???
unsigned int arrBin[0]
The size of an array variable must not be 0. The program is ill-formed. Don't do this.
unsigned int *pArr1 = &arrBin[1];
Here, you use subscript operator beyond the bounds of the array (beyond one past last element), so the behaviour of the program is undefined. Don't do this.
(while I have no idea, how to get the number of items this way).
The number of items is 0 (or would be if that was allowed in the first place).
The other thing I don't understand, is why I can write myInt = myFloat?
You haven't even declared such identifiers.
I'm writing to a static (?) array I had defined as myArray[0] for experimenting.
By 'static' you probably mean 'fixed-sized'. static means something totally different, see https://www.geeksforgeeks.org/static-keyword-cpp/.
So it seems NOT to be static
It is not static, hence, it's not surprising that it's not static.
but sizeof(myArray) always returns 0
Its size is 0, as the size of 0 was specified. While this is not supported by the standards, it's possible that some compilers allow it.
but I can find mem address for each item (while I have no idea, how to get the number of items this way).
&arr[i] yields the address.
The other thing I don't understand, is why I can write myInt = myFloat?
Integer numbers are always real numbers, but real numbers are not always integer numbers. So, how would you store 0.5 as an integer? You could cast it or you could round it.
So, what IS a static array?
In the link I have provided you, it is mentioned that static variables in a function are variables for whom memory is allocated for the whole duration of a program. Hence, a static array is an array declared with the static keyword for which space are allocated for the whole lifecycle of your program. No such array was declared in your function.
And should I better use for an array of undefined length?
This is opinionated. You could create a pointer and navigate to items using pointer arithmetics, achieving the same behavior as with arrays, but without the length being fixed and with a slightly different syntax. Or you could use a library, a vector or whatever fits your task and taste.
This question already has answers here:
How do I find the length of an array?
(30 answers)
Closed 8 years ago.
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]".
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.
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';
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.
This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
sizeof(array) / sizeof(int) [duplicate]
(2 answers)
Closed 9 years ago.
I have written a function size which takes integer array as an argument.
int length(int a[])
{
return sizeof(a)/sizeof(int);
}
int main()
{
int a[] = {1,3,5,6,9,4,2,1,0,0};
int len = sizeof(a)/sizeof(int);
cout << len; // This correctly prints 10 .
len = size(a);
cout << len; // But this print 2 .why ??
return 0;
}
Can someone explain me this behaviour?
Thanks.
The reason you get 2 is because sizeof(int *) is twice as large as sizeof(int), and arrays decay into pointers when passed into a function.
There are various ways to work around this. In C++, you could use a std::vector<int> a = { ... }; instead, which would solve the problem (by calling the a.size() to get the size, as sizeof(a) wouldn't work).
Because sizeof(a) is returning the size of the pointer which will be either 4 bytes or 8 bytes depending upon whether your app is 32-bit or 64-bit. So you would need to maintain the length of your array using a separate variable.
Or, better still, I would recommend using one of the standard collection classes, like std::vector for example since this will maintain the length automatically.
This question already has answers here:
What happens if I define a 0-size array in C/C++?
(8 answers)
Closed 1 year ago.
Today I incidentally defined a two dimensional array with the size of one dimension being 0, however my compiler did not complain. I found the following which states that this is legal, at least in the case of gcc:
6.17 Arrays of Length Zero
However, I have two questions on this usage:
First, is this considered as good programming practice? If so, then when should we use it in real world?
Second, the array I defined was two dimensional, with 0 size for one dimension. Is this the same as the one dimensional case? For example,
int s[0]
int s[0][100]
int s[100][0]
Are they all the same in the memory and for the compiler?
EDIT: Reply to Greg: The compiler I am using is gcc 4.4.5. My intention for this problem is not compiler-dependent, however if there are any compiler specific quirks that would be helpful too:)
Thanks in advance!
In C++ it is illegal to declare an array of zero length. As such it is not normally considered a good practice as you are tying your code to a particular compiler extension. Many uses of dynamically sized arrays are better replaced with a container class such as std::vector.
ISO/IEC 14882:2003 8.3.4/1:
If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.
However, you can dynamically allocate an array of zero length with new[].
ISO/IEC 14882:2003 5.3.4/6:
The expression in a direct-new-declarator shall have integral or enumeration type (3.9.1) with a non-negative value.
I ran this program at ideone.com
#include <iostream>
int main()
{
int a[0];
int b[0][100];
int c[100][0];
std::cout << "sizeof(a) = " << sizeof(a) << std::endl;
std::cout << "sizeof(b) = " << sizeof(b) << std::endl;
std::cout << "sizeof(c) = " << sizeof(c) << std::endl;
return 0;
}
It gave the size of all the variables as 0.
sizeof(a) = 0
sizeof(b) = 0
sizeof(c) = 0
So in the above example, no memory is allocated for a, b or c.
Compiling your example with gcc, all three of them have sizeof 0, so I would assume that all of them are treated equally by the compiler.
Your link explains everything. They are used as last field in a struct when the length of struct is not known at compile time. If you try using them on stack or in a middle of other declarations you will end up overwriting next elements.