This question already has answers here:
How do I declare a 2d array in C++ using new?
(29 answers)
Closed 5 years ago.
I'm trying to understand how to create a dynamic array of pointers in C++.
I understand that new returns a pointer to the allocated block of memory and int*[10] is an array of pointers to int. But why to you assign it to a int**? I'm struggling to understand that.
int **arr = new int*[10];
According to the C++ Standard (4.2 Array-to-pointer conversion)
1 An lvalue or rvalue of type “array of N T” or “array of unknown
bound of T” can be converted to a prvalue of type “pointer to T”. The
result is a pointer to the first element of the array.
So for example if you have an array like this
int a[] = { 1, 2, 3, 4, 5 };
then in this declaration
int *p = a;
the array designator used as the initializer is implicitly converted to pointer to its first element.
So in general if you have array
T a[N];
then in expressions with rare exceptions it is converted to pointer to its first element of the type T *.
In this declaration
int **arr = new int*[10];
the initializer is an array elements of which has the type int *. You can introduce a typedef or an alias declaration
typedef int * T;
or
using T = int *;
So you can write
T * arr = new T[10];
that is the pointer arr points to the first element of the dynamically allocated array. As the elements of the array has the type int * then the type of the pointer to an element of the array is int **.
That is the operator new returns pointer to the first element of the dynamically allocated array.
Related
I am trying to understand pointers in C++, but I am currently confused with the following:
char input_line[] = "hi?";
char* p;
p = &input_line;
while (*p)
{
cout << *p << endl;
*p++;
}
I must be confused here because I would think this says assign the address of a 1d array to the pointer; however, when I try to compile this, I get an error: error: cannot convert char (*)[4]' to 'char*' in assignment p = &input_line;
It looks like I should be doing this:
const char input[] = "test?";
int quest_count = 0;
const char *i = input;
while(*i){
cout << *i << endl;
*i++;
}
This doesn't make sense to me because you are assigning a char array to a char pointer which stores an address.
The error in this line of code:
p = &input_line;
Can be resolved by changing it with:
p = input_line;
That's because your're assigning the memory direction of the array.
Its value is a pointer to a char pointer. That's why the error is
raised. Remember, the operator & gives to you the variables memory
direction.
A pointer stores a memory direction of an object. An array is a sequence of objects by a certain type that are located in consecutives reserved amount of space in memory.
Each index of an array is a number composed of the digits from 0 to 9. Each element of an array is an object that you can take the address of, like a pointer to an object memory location. In an array the objects are located in consecutive memory locations. When you assign an array to a pointer, you're assigning the pointer to the arrays first element, it's array[0].
When you increase by 1 the pointer value, the pointer will point to the next object in a memory location. So, arrays and pointers have similar behavior. If you assign to a pointer an array and then you increase by 1 the pointer value, it will point now to the object in the array.
This is not only for char type, it's for every type in C++. In this page you can get more information about pointers and array. You must note that the pointer and the array must contain or point to the same variable type.
Here's an example from this page:
int* ptr;
int a[5];
ptr = &a[2]; // &a[2] is the address of third element of a[5].
An output example from the example in this page is:
Displaying address using arrays:
&arr[0] = 0x7fff5fbff880
&arr[1] = 0x7fff5fbff884
&arr[2] = 0x7fff5fbff888
&arr[3] = 0x7fff5fbff88c
&arr[4] = 0x7fff5fbff890
Displaying address using pointers:
ptr + 0 = 0x7fff5fbff880
ptr + 1 = 0x7fff5fbff884
ptr + 2 = 0x7fff5fbff888
ptr + 3 = 0x7fff5fbff88c
ptr + 4 = 0x7fff5fbff890
As you can note in the output example, both are pointing to the same memory location, so you can access the objects from both methods.
Formally, in the C++ 11 standard is mentioned that:
Array-to-pointer conversion:
An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to a prvalue of type “pointer
to T”. The result is a pointer to the first element of the array.
You can see those pages for more information about this theme:
C++ Pointer to an Array.
C++ Pointers and Arrays.
C++ Pointer to an Array.
C++11 Standard Library Extensions
From the C++11 standard (emphasis mine):
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.
This conversion, conversion of an array to a pointer to the first element of the array, is commonly know as "an array decays to a pointer to the first element of the array".
This conversion applies to all types, not just char.
int array_1[10] = {};
int* ptr1 = array_1; // ptr1 is a pointer to the first element of array_1
double array_2[10] = {};
double* ptr2 = array_2; // ptr2 is a pointer to the first element of array_2
#include <iostream>
using namespace std;
void printarray (int arg[], int length) {
for (int n = 0; n < length; n++) {
cout << arg[n] << " ";
cout << "\n";
}
}
int main ()
{
int firstarray[] = {5, 10, 15};
int secondarray[] = {2, 4, 6, 8, 10};
printarray(firstarray, 3);
printarray(secondarray, 5);
return 0;
}
This code works, but I want to understand how is the array being passed.
When a call is made to the printarray function from the main function, the name of the array is being passed. The name of the array refers to the address of the first element of the array. How does this equate to int arg[]?
The syntaxes
int[]
and
int[X] // Where X is a compile-time positive integer
are exactly the same as
int*
when in a function parameter list (I left out the optional names).
Additionally, an array name decays to a pointer to the first element when passed to a function (and not passed by reference) so both int firstarray[3] and int secondarray[5] decay to int*s.
It also happens that both an array dereference and a pointer dereference with subscript syntax (subscript syntax is x[y]) yield an lvalue to the same element when you use the same index.
These three rules combine to make the code legal and work how you expect; it just passes pointers to the function, along with the length of the arrays which you cannot know after the arrays decay to pointers.
I just wanna add this, when you access the position of the array like
arg[n]
is the same as
*(arg + n)
than means an offset of n starting from de arg address.
so arg[0] will be *arg
The question has already been answered, but I thought I'd add an answer with more precise terminology and references to the C++ standard.
Two things are going on here, array parameters being adjusted to pointer parameters, and array arguments being converted to pointer arguments. These are two quite different mechanisms, the first is an adjustment to the actual type of the parameter, whereas the other is a standard conversion which introduces a temporary pointer to the first element.
Adjustments to your function declaration:
dcl.fct#5:
After determining the type of each parameter, any parameter of type “array of T” (...) is adjusted to be “pointer to T”.
So int arg[] is adjusted to be int* arg.
Conversion of your function argument:
conv.array#1
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The temporary materialization conversion is applied. The result is a pointer to the first element of the array.
So in printarray(firstarray, 3);, the lvalue firstarray of type "array of 3 int" is converted to a prvalue (temporary) of type "pointer to int", pointing to the first element.
firstarray and secondarray are converted to a pointer to int, when passed to printarray().
printarray(int arg[], ...) is equivalent to printarray(int *arg, ...)
However, this is not specific to C++. C has the same rules for passing array names to a function.
The simple answer is that arrays are ALWAYS passed by reference and the int arg[] simply lets the compiler know to expect an array
I have a question about syntax of pointer to arrays.
Well we know arrays are pointers themselves(what our uni professor said) so why when we point to them with another pointer (which would be a pointer to pointer) we use this syntax:
int array[10];
int *pointer = array;
Instead of this syntax:
int array[10];
int **pointer = &array;
Although i know this would be correct using malloc but why not in the normal way, is it a compiler or syntax thing or i am wrong somewhere else??
Tell your professor they are wrong. Arrays are not pointers. Arrays can decay to pointers, but they are not pointers.
int* pointer = array; declares a pointer that points to the first element in array.
int** pointer = &array; is not correct. As mentioned by jschultz410 in the comments, the type of &array is not int**, it is int (*)[10] aka a pointer to an array of 10 ints, which cannot decay to int**.
Well we know arrays are pointers themselves
No. Arrays are not pointers. Arrays are arrays. Except when it is the operand of the sizeof or the unary & operator, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer toT" and the value of the expression will be the address of the first element of the array. However, no storage is set aside for a pointer in addition to the array elements themselves.
So, given the declaration
int array[10];
the type of the expression array is "10-element array of int"; unless array is the operand of sizeof or unary &, it will decay to type int *. So
int *ptr = array;
works.
The type of &array is not int **; the type is int (*)[10], or "pointer to 10-element array of int". You'd declare and initialize such a pointer as
int (*ptr)[10] = &array;
First of all this definition of a pointer
int array[10];
int **pointer = &array;
is invalid. In the right side of the declaration there is an expression having type int ( * )[10] while in the left side there is identifier of type int **. There is no implicit conversion between pointers int ( * )[10] and int ** . So the compiler shall issue a diagnostic message.
The correct definition will look
int array[10];
int ( *pointer )[10] = &array;
Now we can consider what is the difference between these two definitions
int array[10];
int *pointer = array;
and
int array[10];
int ( *pointer )[10] = &array;
In the first case the size of the object pointed to by pointer pointer is equal to sizeof( int ). So if to use the pointer arithmetic then after evaluation of expression ++pointer the value in the pointer will be increased by sizeof( int ) bytes. If for example sizeof( int ) is equal to 4 then the value in the pointer will be increased by 4.
In the second case the size of the object pointed to by pointer pointer is equal to 10 * sizeof( int ) that is if sizeof( int ) is equal to 4 then the size of the object is equal to 40. So if the pointer will be increased ++pointer its value will be increased by 40.
Also dereferencing the pointer in the first case will give you an object of type int while dereferencing the pointer in the second case will give you an object of type int[10] that is an array.
And arrays are not pointers. Simply they are usually converted to pointers to their first elements in expressions. From the C Standard
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
If you write for example
int array[10];
int *pointer = array;
then sizeof( array ) is not equal to sizeof( pointer ) though you can use the common syntax to access elements of the array:
array[ i ] and pointer[ i ] and will get the same result..
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Arrays and length in C++
(9 answers)
Why sizeof(param_array) is the size of pointer?
(8 answers)
Closed 9 years ago.
I have searched all the way through net but could not find a solution.
I want to find length of an int array (number of elements in the array).
Well I am trying to pass array in the function.
I tried
void myFunction(int array[])
{
int size = sizeof(array)/sizeof(array[0]);
}
but no luck!
Here is the sample code: Sample Code
could any one help me in this?
When arrays are passed into functions, they undergo array-to-pointer conversion. This means an array of type T[N] will simply decay into T*. Notice how the size information has been lost. All that remains is a pointer to the first element of the array. Here is a quote from the Standard:
4.2 Array-to-pointer conversion
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue
of type “pointer to T”. The result is a pointer to the first element of the array.
In short, sizeof( array ) returns the size of the pointer, not of the array. That's where the miscalculation derives. A simple solution would be to utilize dynamic containers like std::vector which contains its size information internally:
#include <vector>
void myFunction(std::vector<int> const &array)
{
int size = array.size();
}
If using std::vector isn't an option, you can use a reference to an array instead while using a template argument to deduce the length:
template <unsigned N>
void myFunction(int (&array)[N])
{
int size = N;
}
#include <iostream>
using namespace std;
void printarray (int arg[], int length) {
for (int n = 0; n < length; n++) {
cout << arg[n] << " ";
cout << "\n";
}
}
int main ()
{
int firstarray[] = {5, 10, 15};
int secondarray[] = {2, 4, 6, 8, 10};
printarray(firstarray, 3);
printarray(secondarray, 5);
return 0;
}
This code works, but I want to understand how is the array being passed.
When a call is made to the printarray function from the main function, the name of the array is being passed. The name of the array refers to the address of the first element of the array. How does this equate to int arg[]?
The syntaxes
int[]
and
int[X] // Where X is a compile-time positive integer
are exactly the same as
int*
when in a function parameter list (I left out the optional names).
Additionally, an array name decays to a pointer to the first element when passed to a function (and not passed by reference) so both int firstarray[3] and int secondarray[5] decay to int*s.
It also happens that both an array dereference and a pointer dereference with subscript syntax (subscript syntax is x[y]) yield an lvalue to the same element when you use the same index.
These three rules combine to make the code legal and work how you expect; it just passes pointers to the function, along with the length of the arrays which you cannot know after the arrays decay to pointers.
I just wanna add this, when you access the position of the array like
arg[n]
is the same as
*(arg + n)
than means an offset of n starting from de arg address.
so arg[0] will be *arg
The question has already been answered, but I thought I'd add an answer with more precise terminology and references to the C++ standard.
Two things are going on here, array parameters being adjusted to pointer parameters, and array arguments being converted to pointer arguments. These are two quite different mechanisms, the first is an adjustment to the actual type of the parameter, whereas the other is a standard conversion which introduces a temporary pointer to the first element.
Adjustments to your function declaration:
dcl.fct#5:
After determining the type of each parameter, any parameter of type “array of T” (...) is adjusted to be “pointer to T”.
So int arg[] is adjusted to be int* arg.
Conversion of your function argument:
conv.array#1
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The temporary materialization conversion is applied. The result is a pointer to the first element of the array.
So in printarray(firstarray, 3);, the lvalue firstarray of type "array of 3 int" is converted to a prvalue (temporary) of type "pointer to int", pointing to the first element.
firstarray and secondarray are converted to a pointer to int, when passed to printarray().
printarray(int arg[], ...) is equivalent to printarray(int *arg, ...)
However, this is not specific to C++. C has the same rules for passing array names to a function.
The simple answer is that arrays are ALWAYS passed by reference and the int arg[] simply lets the compiler know to expect an array