line of code giving me trouble

hi guys I have come across a line of code while studying that is giving me trouble this is the block of code

1
2
3
4
5
6
7
8
9
10
  #include <iostream>

int main() {
    const char* a[3] = { "one", "two", "three" };
    const char*(*p)[3] = &a;
    for(int i = 0; i < 3; i++) {
        std::cout << *p[i] << std::endl; // this line
    }
    return 0;
}


this is the link of the question he asked

https://stackoverflow.com/questions/16013450/dereferencing-a-pointer-to-an-array

anyway the line of code that has me confused is

 
const char*(*p)[3] = &a;


I thought in order to declare a pointer you would do something like this

const char* p = &a;

but why did he put the p like this (*p) [3]

why is he using the dereferencing pointer on a pointer that is only been declared right there? also why does he put [3] after it?

and also he declares a char pointer but in the same line after the = he says
{ "one", "two", "three" };

I don't know how this is possible

shouldn't it be

1
2
3
4

char array[3] = {'a','b','c'};
char *a = array;


I really just don't understand how all of that block of code works
a is an array of 3 pointers to const char.
p is a pointer to an array of 3 pointers to const char.

Yes the syntax for declaring a pointer to an array is a bit confusing because you have to put the asterisk and the variable name inside parentheses but it's necessary otherwise the compiler would think the asterisk was part of the element type.

1
2
int *x[5]; // an array of 5 pointers to int.
int (*y)[5]; // a pointer to an array of 5 ints. 
Last edited on
const char*(*p)[3] is a pointer to an array of 3 pointers to a constant char.

Or maybe a more intuitive way to say it: a pointer to an array of 3 constant C strings.

To read these kind of expressions you need to know some rules:
1. const applies to anything to its immediate left (or if there is nothing to the left, then to whatever is to its immediate right)
2. Start at the identifier name. First, look to your right. If there is a [n] read it as 'array n of'. Now look to your left. If there is a * read that as 'a pointer to'. If there are multiple [n][m] read it as 'array n of array m of'. If there are multiple ** read it as 'a pointer to a pointer to'. The arrays always have precedence over *.
3. Go up one level (in parentheses) and repeat the algorithm in 2.

Example:
1
2
3
4
5
p                   //p 
*p                  //p is a pointer 
(*p)[3]             //p is a pointer to an array 3
*(*p)[3]            //p is a pointer to an array 3 of pointers
const char *(*p)[3] //p is a pointer to an array 3 of pointers to a const char  


A tool that can help you in the beginning https://cdecl.org/
Last edited on
thanks guys much appreciated

if a is an array of pointers to const char's what is the right hand side doing?

const char* a[3] = { "one", "two", "three" };

how can we the pointers in this way?

I thought a pointer holds a memory address but here we are passing the values in as strings?

I thought that before the declaration above call we would have created 3 const c style strings then assigned the char instead of doing this = { "one", "two", "three" };

I'm not exactly sure how and why that works
Last edited on
also what would be the difference between declaring


const char *(*p)[3] = &a;

and

const char** p = &a
If a is an array of pointers to const char's what is the right hand side doing?

The right hand side is giving you three const char * pointers.
Each literal is a const char pointer to a C-string. The initialization list consists of three const char * pointers which matches the declaration of a[3] perfectly.

I thought a pointer holds a memory address

It does.

I thought that before the declaration above call we would have created 3 const c style strings

The result of creating the strings was the address of each of the C-style strings.
Last edited on
= { "one", "two", "three" };

I'm still kind of confused

why do we put "" marks in between the names I thought when naming variables you use name them without the "" marks

also is the code creating three pointers to const char named one two and three?

or are we actually creating three c style strings?

I understand

const char a[3] = {"one","two","three"};

this is possible because we're declaring the strings in proper format

where as I thought if we were to create initialise three pointers to chars that are const

we would do something like this

const char* a[3] = {&one,&two,&three};

in the example code there was no const chars declared ?

thanks
Last edited on
I understand

const char a[3] = {"one","two","three"};

this is possible because we're declaring the strings in proper format

That code doesn't compile. const char a[3] is an array of just three characters.

You could initialise it like this:
 
    const char a[3] = "on";
or like this:
 
    const char a[3] = {'o', 'n', '\0' };

Remember a c-string has a null-terminator so the string "on" requires three characters of storage.
Last edited on
thanks for the reply guys

but how come we can do this

const char* a[3] = { "one", "two", "three" };
?
Well, to briefly return to the previous example. A C-string can be declared like this:
 
char a[4] = "one";
but it can also be declared like this:
 
const char* a = "one";


In the first, we declare an array. The second, there is no array, just a pointer. The pointer is pointing to the C-string which the compiler has placed somewhere in read-only memory.

The array const char* a[3] = { "one", "two", "three" }; contains three such pointers. The strings themselves are placed in some location determined by the compiler. We are not declaring storage for the actual strings. Just the pointers which point to those strings.

hi Chervil thanks for the reply,


so basically in the second example a[3] is a pointer array to const chars and by doing using the initialisation block {} we are setting the values of what ever these pointers point to,to a c style string?

so for example a[0] = some memory address that holds the string "one"?

this seems quite confusing

thanks
so for example a[0] = some memory address that holds the string "one"?


The address doesn't 'hold the string'. It points to the location where the string is held. (or maybe I misunderstood your wording).

Take a look at each of the following examples. There are a few variations, see if they make sense.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>

using namespace std;

int main()
{
    // create ordinary arrays of characters
    char first[]  = "one";
    char second[] = "two";
    char third[]  = "three";
    
    
    // output string stored in character array       
    cout << "second = " << second << '\n';
    
    
    // create char pointer, give it address of array third
    char * p = third;
    
    // output string pointed to by char pointer p
    cout << "p = " << p << '\n';
    
    
    // allocate array of pointers
    // store address of array 'first' in a[0]
    // store address of read-only string "four" in a[1]
    
    const char * a[2] = { first, "four"  };

    cout << "a[0] = " << a[0] << '\n';
    cout << "a[1] = " << a[1] << '\n';
     
}


Output:
second = two
p = three
a[0] = one
a[1] = four

Last edited on
Topic archived. No new replies allowed.