***Pointers to Pointers?

Pages: 12
I'm very confused about Pointers to Pointers.
See the below code.

I have been told that ***a represents a three dimensional array__ but I'm not sure sure this is right. My understanding of that answer is that
int ***a = a[x][y][z]; which just gives an error (of course I would specify the type), when I try to compile it.

I know that *a points to the first value in an array a[x]. //but it's after this where I get lost.

If a function for example Funct(int ***a, int **b) requires me to have the ***a and ***b inputs, what do I put in these parameters when I call Funct?

Do I use Funct(**a[x], **b[y])?

Do I use just separate int values x & y like Funct(x,y) and go on treating ***a and ***b like a normal pointer variable? If I do, then what's the point?


I'm just not sure why I would even use ***a or ***b at all. In my example below, I can't imagine why you would go through the trouble of re-assigning pointers just to add another layer of dereferencing?


1
2
3
4
5
6
7
8
9
10
11
int main()
{
// the below works
int d = 15;
int *c = &d;
int **b=&c;
int  ***a = &b;
cout << ***a << endl;  //the output for ***a is 15.

system("pause>nul");
}
Hello guy,
I hope this helps you.

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
#include <algorithm>
#include <stdlib.h>

using namespace std;

void fill(int& value){
	static int val = 0;
	val++;

	value = val;
}

void zero(int& value){
	value = 0;
}


void mult(int* **A,int* **B,int* **result, const int SIZE) {
	for (int i = 0; i < SIZE; i++)
		for (int j = 0; j < SIZE; j++)
			for (int k = 0; k < SIZE; k++)
				(*result)[i][j] += B[0][i][k] * (*A)[k][j];
}

int main(){
	int *vector;
	const int SIZE = 3;

	//reserve memory:
	vector = (int*) malloc(sizeof(int) * SIZE);
	for_each(vector,vector + SIZE,fill); //fill

	//print
	for(int i = 0 ; i < SIZE ; i++)
		cout << vector[i] << ", ";
	cout << endl << endl << endl;

	//reserve memory for a pair of matrices:
	int**matrix;
	matrix = (int**) malloc(sizeof(int*) * SIZE );
	for(int i = 0 ; i < SIZE ; i++ )
		matrix[i] = (int*) malloc(sizeof(int) * SIZE);

	int**result;
	result = (int**) malloc(sizeof(int*) * SIZE );
	for(int i = 0 ; i < SIZE ; i++ )
		result[i] = (int*) malloc(sizeof(int) * SIZE);
	//***************************

	//fill matrix:
	for_each(matrix[0],matrix[0] + SIZE,fill);  for_each(result[0],result[0] + SIZE,zero);  
	for_each(matrix[1],matrix[1] + SIZE,fill);  for_each(result[1],result[1] + SIZE,zero);
	for_each(matrix[2],matrix[2] + SIZE,fill);  for_each(result[2],result[2] + SIZE,zero);

	//print it
	for(int i = 0 ; i < SIZE ; i++){
		for(int j = 0 ; j < SIZE ; j++)
			cout << matrix[i][j] << ", ";
		cout << endl;
	}
	cout << endl << endl << endl;

	mult(&matrix, &matrix, &result, SIZE);
	//print it
	for(int i = 0 ; i < SIZE ; i++){
		for(int j = 0 ; j < SIZE ; j++)
			cout << result[i][j] << ", ";
		cout << endl;
	}
	cout << endl << endl << endl;

	system("pause");

	return 0;
}


By the way, I recommend to use std::vector instead of 2d array, it's safer and easier.

Thanks for the effort. But what I'm trying to do is interpret functions provided by another external library. They require function parameters such as ***var1 and **var2 but I'm just not sure what to put in their place?

Do I put a pointer to an array for ***var1 such as *var[x]? Or do I put a reference to an array such as &var1[x]? If so, how do I do this.

Is it by saying int *var1[x] = 1 or by var 1 = &var1[x] then var1[x] = 5 for example? I'm trying to understand these pointer of pointer arguments so I can use them.

Thanks again.
It will depend on the function. You'll have to look at the documentation for the library you're using to find out what the function is expecting to receive.
Last edited on
Ok.. Well, there can only be so many options.
If the function is asking for a int ***var then what can I put there?

Does ***var mean that I should enter a variable allocated to ***var such as
int ***var = 1; or does it mean that I should enter a int &array1[x] or does it mean that I should enter a int array1[x][y][z]; because from what I am told a int *** var is equivalent to a three dimensional array (which I think is wrong). The documentation does not tell me squat..... As usual....

To cut it down.. what does ***var1 as for... What do I put in it's place if a function is calling for this type of pointer of a pointer variable?

It's a pointer to a pointer to a pointer. That's all I can tell you. Documentation of the library you're working with should tell you the expected input. If not, ditch that library if you can.
Notice that I used malloc to reserve memory, in the case you just declare a matrix using int matrix[SIZE][SIZE];( static in compiler time ) you wouldn't be able to pass as argument as int ***( &matrix ) because the type, indeed, is (*)[SIZE][SIZE].

So in the previous example would be like this:

1
2
int result[SIZE][SIZE];
void mult(int* **A,int* **B,int (*result)[3][3], const int SIZE);


Thus, if you reserve memory dynamically for int*** you would be able to pass it as argument(***) and access using [][][] but in static would that's different.


If you want more help try to write down more information about the library.
Thanks.. I am at a loss as to how I can get this to work. This is for Sqlite.

I even have a book in front of me (the latest edition mind you) which has mistakes in it. I'm amazed.

I'm looking at the sqlite3_get_table function. I know it has been depreciated but it is also being maintained for back compatibility so it should work. I'll also past a link to the same information on the website below. See my comments.


http://www.sqlite.org/c3ref/free_table.html

1
2
3
4
5
6
7
8
int sqlite3_get_table(
  sqlite3 *db,          /* An open database */
  const char *zSql,     /* SQL to be evaluated */
  char ***pazResult,    /* Results of the query */
  int *pnRow,           /* Number of result rows written here */
  int *pnColumn,        /* Number of result columns written here */
  char **pzErrmsg       /* Error msg written here */
);


The example of how to use it is below. This came from the source code from the book. There seems to be nothing in the world I can do to get this to work. I have included all the right headers.. everything.


1
2
3
4
5
6
7
8
9
10
11
12
13
int main(int argc, char **argv)
{
    /* Connect to database, etc. */

    char *result[];    // for starters, this causes an error?
    sql = "select * from episodes;";
    rc = sqlite3_get_table(db, sql, &result, &nrows, &ncols, &zErr);

    /* Do something with data */

    /* Free memory */
    sqlite3_free_table(result)
}
char *result[]; yea, this causes an error.

Generally, if you use a c-string and use [] is expected to initialize at the same time, I mean:

1
2
	char*result[] = { "one", "two" };
	cout << result[0] << ", " << result[1] << endl;


So the compiler can deduce the size of result and you got the freedom not to count the number of words you are writing.
This idea is also in arguments of functions. Then, it's more like a normal pointer.

In this case, personally, I think you might use char **result; because I'd hope that the sqlite3_get_table takes care about reserving memory (insomuch as you wanna get the table) and pass it as reference(because it's like an output), for me, the example of the book seems legit (It's the way I would expect to use it).

What are you trying exactly and which error gives compiler?
Just doing a quick google, it would appear result is an array of pointers to c-strings, with the memory being owned by the sqlite library.

//www.sqlite.org/c3ref/free_table.html

So result should be:

char ** result ;
as i understand it:
(***a)

0x1245678 0x34567891 0x56789123 something of type <a>
---------------__> --------- _>--------- __>----------
address 0x1245678 0x34567891 0x56789123


ofcourse you cant use a[x][y][z] as you havent allocated memory to it....

and it seems logical to me that when calling a function you just have to pass the first address as it contains the next adress

what i am trying to say is that ***a doesnt represent a 3 dimensional array
but ***a= new <type>[10][10][10] does
Last edited on
I understand what you have all said.. I just can't work out how to apply it. There is not one single working example on the internet as far as I can see.

I believe that the sql string is read and the rest of the details are determined from that.. This probably sounds very naive. I'm not the most knowledgeable programmer in the world.

There's no indication whether I should indicate the row and column count so I'm assuming this information is extracted when the sql string is read.

As for the result. The only form which will compile is as per below. The only problem is that when I try to execute the executable, it crashes and doesn't tell me anything else. I'm assuming it happens because result hasn't picked anything up. This one is a real mystery.

The result[] array is supposed to provide the below type of output. This came from the sqlite website. My code is below that.

Name | Age
-----------------------
Alice | 43
Bob | 28
Cindy | 21
There are two column (M==2) and three rows (N==3). Thus the result table has 8 entries. Suppose the result table is stored in an array names azResult. Then azResult holds this content:

azResult[0] = "Name";
azResult[1] = "Age";
azResult[2] = "Alice";
azResult[3] = "43";
azResult[4] = "Bob";
azResult[5] = "28";
azResult[6] = "Cindy";
azResult[7] = "21";


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
34
35
36
37
38
39
40
#include <iostream>
#include "sqlite3.h"
#include <cstdlib>
#include <cstdio>

using namespace std;

int sqlite3_get_table(sqlite3 *db, const char *Sql, char ***result, int *rows, int *cols,char **ermsg);



int main()
{

sqlite3 *db;
char *zErr;
int rc;
int kt;
char *zsql;
int row;
int col;
char **result=NULL;


rc = sqlite3_open_v2("foods.db", &db, NULL, NULL);



zsql ="select * from foods;";



kt  = sqlite3_get_table(db, zsql, &result, &row, &col, NULL);

cout << result[5] << endl;  //THIS LINE CRASHES MY EXE FILE.  THAT TELLS ME THAT NOTHING IS PICKED UP IN RESULTS


system("pause>nul");

}
Last edited on
You might bother checking if the call succeeded first.

1
2
3
4
5
6
7
8
9
if ( SQLITE_OK == sqlite3_get_table(db, zsql, &result, &row, &col, NULL))
{
    for ( unsigned row=0; row < rows+1; ++row )
    {
        for ( unsigned col=0; col < cols;  ++col )
            std::cout << result[row*col+col] << '\t' ;
        std::cout << '\n' ;
    }
}
Ha.. Thanks.

Looks like the call hasn't succeeded. I'm yet to figure out why and have no idea at this point.

I think I need to understand debugging a little better. It's probably a very important pre-requisite for professional programmers for this very reason.

Maybe you should try using the last parameter (get back an error message).

Just wanted to let everyone know I'm in a state of shock......

The sqlite3_get_table function has now worked.. at long last.


The problem appears to have been with the sqlite3_open_v2 function. More specifically it has to do with how I used this function.

sqlite3_open_v2("foods.db", &db, NULL, NULL);

I should have included the third argument flag SQLITE_OPEN_READWRITE to make this work.. I took it out for some reason, but this version of open works when I included it again.

Here's the Sqlite website interpretation of it.

1
2
3
4
5
6
int sqlite3_open_v2(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb,         /* OUT: SQLite db handle */
  int flags,              /* Flags */
  const char *zVfs        /* Name of VFS module to use */
);


All I did is use the below version by cutting off the v2 (which is the latest version and using the below version.

int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);

My code is now: rc = sqlite3_open("foods.db", &db);
Though the v2 version also works fine.

I'm still not sure why, if the sqlite3_get_table function requires a
char ***result argument it works to declare a char **result argument and input a &result in the parameter... It's very confusing?
Last edited on
It's like to say that the argument is pointing to a 2d-array (it makes sense, I hope so).

Normally, you got:

1
2
3
4
int *a;
int b = 10;

a = &b;


So, it's the same idea.
Thanks again.. Got it working well now and the above makes sense.

I have one more question, whilst I'm on the subject. Not sure if I should start a new thread but can do so if need be. I'll lay it out below.

I declare the sqlite3_get_table parameters as per below.

1
2
3
4
5
6
const char *zsql;
int row;
int col;
char **result=NULL;
sqlite3 *db;
int kt;


Sqlite, specifies that the parameters should be as per below.

int sqlite3_get_table(sqlite3 *db, const char *Sql, char ***result, int *rows, int *cols,char **ermsg);

But... the function is only successful when I use sqlite3_get_table function with the below parameters.

sqlite3_get_table(db, zsql, &result, &row, &col, &zErr);


I now understand why the ***result parameter requires an address &result in the function arguments, we've been through that one.

But, I'm not sure why, for example, the row and col parameter is indicated by sqlite as requiring an int pointer variable (int *row and int *col) when I can only declare a normal int variable (int row and int col) to make this work. If I declare row and col as pointers I get an error.

I have one theory as to why: Would it be to do with where these parameters are defined? For example, the zsql parameter is read and produced outside the scope of the function call so we would declare this as a pointer variable. But.. the row and col parameters are defined as a result of the returned zsql string (the actual returned data) so we only declare these as normal (non-pointer) variables to make this work. The address of the col and row variables are used as part of the generating of the query which ultimately loads the result array?
I hope that's not too confusing. I'm not overly advanced in this area but I want to work this out because it will surely help me apply other sqlite functions easier than I found this one.

Thanks.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

void byPtr( int* n )
{
    *n = 10 ;
}

void byVal( int n )
{
    n = 10 ;
}

int main()
{
    int a=0, b=0 ;

    byPtr(&a) ;
    byVal(b) ;

    std::cout << "a: " << a
              << "\nb: " << b << '\n' ;
}
a: 10
b: 0
Gotcha. I see how this works now.
My only question with this is, if sqlite advertises the arguments to
their API Functions as requiring a pointer variable, but in fact, passing by value is the only way it will work, then how is the user supposed to know that the value is to be passed by value and not by reference?

I can see some indications of what is required in the source file but is it normal practice to have to open these to find out this kind of information?

Pages: 12