This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 8 years ago.
In C# I use the Length property embedded to the array I'd like to get the size of.
How to do that in C++?
It really depends what you mean by "array". Arrays in C++ will have a size (meaning the "raw" byte-size now) that equals to N times the size of one item. By that one can easily get the number of items using the sizeof operator. But this requires that you still have access to the type of that array. Once you pass it to functions, it will be converted to pointers, and then you are lost. No size can be determined anymore. You will have to construct some other way that relies on the value of the elements to calculate the size.
Here are some examples:
int a[5];
size_t size = (sizeof a / sizeof a[0]); // size == 5
int *pa = a;
If we now lose the name "a" (and therefor its type), for example by passing "pa" to a function where that function only then has the value of that pointer, then we are out of luck. We then cannot receive the size anymore. We would need to pass the size along with the pointer to that function.
The same restrictions apply when we get an array by using new. It returns a pointer pointing to that array's elements, and thus the size will be lost.
int *p = new int[5];
// can't get the size of the array p points to.
delete[] p;
It can't return a pointer that has the type of the array incorporated, because the size of the array created with new can be calculated at runtime. But types in C++ must be set at compile-time. Thus, new erases that array part, and returns a pointer to the elements instead. Note that you don't need to mess with new in C++. You can use the std::vector template, as recommended by another answer.
Arrays in C/C++ do not store their lengths in memory, so it is impossible to find their size purely given a pointer to an array. Any code using arrays in those languages relies on a constant known size, or a separate variable being passed around that specifies their size.
A common solution to this, if it does present a problem, is to use the std::vector class from the standard library, which is much closer to a managed (C#) array, i.e. stores its length and additionally has a few useful member functions (for searching and manipulation).
Using std::vector, you can simply call vector.size() to get its size/length.
To count the number of elements in a static array, you can create a template function:
template < typename T, size_t N >
size_t countof( T const (&array)[ N ] )
{
return N;
}
For standard containers such as std::vector, the size() function is used. This pattern is also used with boost arrays, which are fixed size arrays and claim no worse performance to static arrays. The code you have in a comment above should be:
for ( std::vector::size_type i(0); i < entries.size(); ++i )
( assuming the size changes in the loop, otherwise hoist it, ) rather than treating size as a member variable.
In C/C++, arrays are simply pointers to the first element in the array, so there is no way to keep track of the size or # of elements. You will have to pass an integer indicating the size of the array if you need to use it.
Strings may have their length determined, assuming they are null terminated, by using the strlen() function, but that simply counts until the \0 character.
Als Nolrodin pointed out above, it is pretty much impossible to get the size of an plain array in C++ if you only have a pointer to its first element. However if you have a fixed-size array there is a well-known C trick to work out the number of elements in the array at compile time, namely by doing:
GrmblFx loadsOfElements[1027];
GrmblFx_length = sizeof(loadsOfElements)/sizeof(GrmblFx);
Related
My function receives an array as a parameter but the array decays to a pointer so sizeof() doesn't work. I'm not allowed to import any extra libraries and the array was passed as int arr[]. when I searched it up, most people just say to define it outside of the function and pass it in as an argument but I can't do that. so is there a way for me to get the array size?
There are three ways (well two really, as two of the ways are basically the same just with different classes):
Use std::vector instead of array and use the size function to get the number of elements
Use std::array instead (which is really the same as the first)
Use templates and pass the array by reference:
template<size_t N>
void my_function(int (&my_array)[N])
{
std::cout << "The number of elements in the array is " << N << '\n';
}
If you let the array decay to a pointer, all that you have is that pointer to a single element of your array. There's no information about the array itself, like its size. When using pointers you need to pass the size as a separate argument.
If you're not allowed to change the function signature, and the function only takes a pointer as an argument, there's really no way to get the size of the array. For an interview question this is probably the answer you should give.
If it's an assignment given at school or similar you have to talk to the teacher and tell them it's impossible, or come up with an algorithm where you don't need the size explicitly (like adding some kind of terminator to the array, similar to the way that C-style strings are terminated).
I want to know whether a pointer is pointing to an array or single integer. I have a function which takes two pointer (int and char) as input and tell whether a pointer is pointing to an array or single integer.
pointer=pointer+4;
pointer1=pointer1+4;
Is this a good idea?
Like others have said here, C doesn't know what a pointer is pointing to. However if you should choose to go down this path, you could put a sentinel value in the integer or first position in the array to indicate what it is...
#define ARRAY_SENTINEL -1
int x = 0;
int x_array[3] = {ARRAY_SENTINEL, 7, 11};
pointer = &x_array[0];
if (*pointer == ARRAY_SENTINEL)
{
// do some crazy stuff
}
pointer = &x;
if (*pointer != ARRAY_SENTINEL)
{
// do some more crazy stuff
}
That's not a good idea. Using just raw pointers there's no way to know if they point to an array or a single value.
A pointer that is being used as an array and a pointer to a single values are identical - they're both just a memory address - so theres no information to use to distinguish between them. If you post what you want to ultimately do there might be a solution that doesn't rely on comparing pointers to arrays and single values.
Actually pointers point to a piece of memory, not integers or arrays. It is not possible to distinguish if an integer is single variable or the integer is an element of array, both will look exactly the same in memory.
Can you use some C++ data structures, std::vector for example?
For C++ questions, the answer is simple. Do not use C-style dynamic arrays in C++. Whenever you need a C-style dynamic array, you should use std::vector.
This way you would never guess what the pointer points to, because only std::vector will be holding an array.
My function receives an array as a parameter but the array decays to a pointer so sizeof() doesn't work. I'm not allowed to import any extra libraries and the array was passed as int arr[]. when I searched it up, most people just say to define it outside of the function and pass it in as an argument but I can't do that. so is there a way for me to get the array size?
There are three ways (well two really, as two of the ways are basically the same just with different classes):
Use std::vector instead of array and use the size function to get the number of elements
Use std::array instead (which is really the same as the first)
Use templates and pass the array by reference:
template<size_t N>
void my_function(int (&my_array)[N])
{
std::cout << "The number of elements in the array is " << N << '\n';
}
If you let the array decay to a pointer, all that you have is that pointer to a single element of your array. There's no information about the array itself, like its size. When using pointers you need to pass the size as a separate argument.
If you're not allowed to change the function signature, and the function only takes a pointer as an argument, there's really no way to get the size of the array. For an interview question this is probably the answer you should give.
If it's an assignment given at school or similar you have to talk to the teacher and tell them it's impossible, or come up with an algorithm where you don't need the size explicitly (like adding some kind of terminator to the array, similar to the way that C-style strings are terminated).
In the following code, im trying to build 2 arrays. The first one is an array given by the user, the second one is an array which has been sorted among other things, although kept short since the actual implementation is not nescessary :
int main()
{
int size = 0;
cout << "Please enter size: ";
cin >> size;
int array[size];
int newArray[size] = doSomething(array,&size);
return 0;
}
int* doSomething(int array[],int *size)
{
*size+=1;
int newArray[size];
//do something with the array and store it in the newArray
return newArray;
}
So my question is this:
My teacher told me that most compilers work differently, and the order of some operations might differ among them.
At the line int newArray[size] = doSomething(array,&size); I am expecting the size variable to be changed inside doSomething before it is used to initialize newArray. Once the doSomething method is finished running, it should return an array (WHICH I ASSUME It IS JUST RETURNING THE ADRESS OF THE FIRST ELEMENT OF THE ARRAY, PLEASE CORRECT ME IF THIS IS WRONG). Once it returns I want to store that address into my newly array, where the variable size is used to initalize the array's size. This variable should be according to my logic, equal to the original size entered by the user +1. So if the user enters a size of 4, the size of newArray should be 5. Is this a good way of going about it, or would it produce unreliable results for different compilers?
For the purpose of this exercise, I can only use built in array and pointers. So I cannot use vectors. Furthermore, in this example, the newArray is one element larger, but the actual code has a size which is dynamic, and therefore might be different each time. I can therefore not hard code the +1 inside the declaration.
If this is wrong, can someone point me in the right direction and help me to find a way where I can pass a built in array (no vectors or array<>), modify the contents and size of it and then return that array and store it in a variable in the caller method?
Thank you very much
First, standard C++ does not allow so-called variable-length arrays (VLAs); the size of the array in the declaration must be a compile-time constant. Standard C does allow them and both gcc and clang implement them as an extension. So technically, your code is ill-formed C++.
Let's accept the extension, for argument's sake. Now we have another problem, which is that arrays cannot be used as initializers for arrays. (An array could be used to initialize a pointer because the array will decay to a pointer in that context, but the pointer doesn't have a size at all. If you did tgat, though, you would introduce a different problem: the returned array has automatic storage duration which means that it is destructed and deallocated immediately. It is, therefore, a "dangling pointer" and using it is undefined behaviour.) You could work around that restriction a bit awkwardly by wrapping the array in a struct.
None of that touches the order of evaluation issue you are curious about. The answer is that the order is unspecified; the compiler might evaluate the function call before or after allocating space for the array. So even if your compiler allows VLAs, the size of this one is unspecified.
You have a problem here:
cin >> size;
int array[size];
Unless you use new you can't do that. The compiler creates the array container before the program runs, so you can't give it a custom size once it is running.
You must allocate your array as a new object on the heap:
cin >> size;
int* array = new int[size];
Maybe this will point you in the right direction, but I have no idea exactly what classes you are trying to call as you haven't included all of your source code.
I edited my previous answer, because I believe you are trying to simply call an array of ints, not a class called "array". If you just want a C-style array of integers, the above example is how you do it properly.
Keep in mind once you are done using the data you should call
delete[] array;
I have a class that has a large 2 dimensional array in it. It used to be a dynamic array allocated on the heap and now it is statically sized which I prefer.
private:
int fontTextureCoords_[100][7];
I had to add the type casting to the the accessor in order to return the array for access outside the class which is currently working okay, but I'm not sure it is safe or the correct way to handle this.
public:
inline int **getFontTextureCoords()
{
return (int**)fontTextureCoords_;
}
Is this safe / the correct way to do this or is there a more preferred method for returning a pointer to a multi-dimensional array?
That's not the correct way to do that and shouldn't compile. A 2d array is not convertible to a pointer to pointer. You'd have to return a pointer to an array, which is easiest to write using a typedef:
using T = int[7];
inline T* getFontTextureCoords() { return fontTextureCoords_; }
Although it'd be much better to just return a reference the full array:
using T = int[100][7];
inline T& getFontTextureCoords() { return fontTextureCoords_; }
You could also just std::array<std::array<int, 7>, 100>.
Maybe this diagram shows you the difference between the two types of multi-dimensional array declarations. (Sometime people don't understand this.)
The first one says a is a single block of 100 consecutive 7-int chunks, or 700 ints total, all together in one piece.
The second says a is an array of pointers, where each pointer points to a different chunk of ints, scattered all over memory.
The compiler needs to know this, because if you write a[i][j] it has to generate totally different code.
Casting an array such as int fontTextureCoords_[100][7]; to an int** is not right. It leads to undefined behavior.
If it is not too much, change getFontTextureCoords to:
inline int (*getFontTextureCoords()) [7]
{
return fontTextureCoords_;
}
and use it as:
int (*ptr)[7] = getFontTextureCoords();
If you have the option of using std::vector or std::array, it will be better to use them.
There are no multi-dimensional arrays in C/C++. There are only single dimenstional arrays. You can have a single-dimensional array, with every element of it being another single dimensional array. While there seem to be no difference, it is there and is very important.
This is exactly way transitive logic doesn not work. Everybody has gone through it. 'If single-dimensional arrays are passed as a pointer to the first elelement, 2-D arrays should be passed as a pointer to pointer to first element, etc'. But since it is not a two-dimensional array, but array of arrays, the logic can not be applied.
You can reason about it in the following way. Let's say, you have an array of types X.
X x[10];
How do you access element number 5? Easy -
x[5] = 42;
But what compiler does when it sees it? It does approximately this:
*(&x[0] + 5) = 42;
So it takes the address of the first element, and adds 5 to it to get to the address of your 5th element. But what adding 5 means? In bytes, how many bytes should be skipped from address of beginning of the array to arrive at requested memory location? Of course, 5 * sizeof(X). Now, if you have '2-D' array, declared like this:
X x[2][3];
And you try to work with it through the pointer to pointer:
px = (X**)x;
px[3][4] = 42;
Remember, to genereate the code for [][], compiler needs to express in the way of *(px + ). And something has to be the size of the array (as elements of your array are arrays). But you need to know array size for this, and as you can see, your px does not have any array size encoded in it. The only size it know is size of X, which is not enough.
Hope it makes sense, and explains why you can't use int** instead of x[][].