Help with Pointer syntax

Hi,

I'm going through a tutorial/quiz thing, and I think I generally get the basic concept of pointers, but I seem to struggle with understanding the syntax properly.

The three problems below I can obviously compile and get the correct answers, but I have difficulty explaining to myself exactly what is happening. If I was able to better comprehend what is going on, and explain it to myself, then that would be really helpful in making some progress.

If anyone is able to relate in plain English the bits of code which I've marked, then I'd be most appreciative.

Problem 1
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;

int main(){
  char t[3][3], *p=(char *)t;  // I don't get the  *p=(char *)t syntax
  for (int i=0; i<9; i++)
    *p++='a'+i;          // this seems to increment the pointer itself
  cout << t[1][1];       // and the value of the element it points to is
                         // updated/created.
return 0;
}


Problem 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

int main(){
  float *ft[3] = {new float[3], new float[3], new float[3]}, *p; // What???

  for (int i=0; i<3; i++){
    p=ft[i];               // Yeah, this problem confuses me. I don't
    *p=p[1]=*(p+2)=10*i;   // seem to get the difference/syntax between  
  }                        // p and *p (along with several other things)
  cout << ft[1][1];

  delete [] ft[0];
  delete [] ft[1];
  delete [] ft[2];
  
return 0;
}


Problem 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

int main(){
  int *it[3];   // Yeah, even this confuses me. What's it actually creating?
  
  for (int i=0; i<3; i++) {
     it[i]=new int[i+1];

     for (int j=0; j<i+1; j++)
        it[i][j] = 10*i+j;
  }
  cout << it[2][2];

  for (int i=0; i<3; i++)
        delete [] it[i];

return 0;
}


Any assistance gratefully received! I really would like to be able to look at problems like this and verbally explain to myself what they're doing, but right now I get mighty confused with pointer creation and dereferencing, etc.
in a variable creation, * makes something a pointer. anywhere else, it dereferences it. More on that follows.

1) *p=(char *)t;

(type)something is a C style cast. Its a lot less to type than <somekindacast> c++ syntax so you still see it a lot.

t is a 2-d array, as you defined it. the name of t, then, can be treated as a char** type variable. The name of any array can be treated in many ways as if it were a pointer of the type of the array. Or more specifically as a constant pointer; you can't new it or change it!

variables can be declared in a list with initializations.

int x,y=3; //x and y are 2 integers created here, y has an initial value.


put all that together and you get

char * p (created here as part of a variable creation list with commas) is assigned the value of the address of t[0], so p[0] is the same as t[0][0] and p[1] is the same as t[0][1] and p[2] is the same as t[0][2] and so on.


2d arrays are assigned in memory as one single block of memory in 1-d. (memory is 1-d).

so p is going to go out of bounds on t[0][3] (or so you may think!) but that is going to flow into t[1][0] due to how the memory is aligned. So they are using p to unroll a 2-d loop into a 1-d loop, and exploiting the memory alignment to fill in the 't' 2d array. You CANNOT do this for a type** variable assigned with multiple new statements!!!! The memory is not aligned (it could be, but probably isn't) and p will go out of bounds for real in that scenario.


Last edited on
2)
another case of several variables in one statement. its the same as
float *p; //p is a pointer to float type.
ft is an array of pointers of float type, and it initialized them with new statements. ft is a 2-d array, pointer style instead of [][] style.


its similar but different. p is set each loop to ft[index], the first dimension of the 2d construct, and then each of the 3 entries in ft[index][each] is set to the same value (10*I). this is like a statement saying x=y=z=3; ///all 3 are set to 3 here. I don't care for this sort of thing generally, its harder to read than it needs to be.

*p is the thing p points to. its the same as p[0].
p is the pointer, p.

a simpler example:
int x = 5;
int *p = &x; //p points to x.
*p is 5.
p is the address of x, probably some 20 digit integer value in ram somewhere.

These examples are not good code. They are great examples of pointer nonsense, which you will encounter out in the wild, but please don't think you should code LIKE this.

problem 3...
int *it[3];
by now you should see this one.
its an array of 3 integer pointers, a 2-d array of integers is the result. Its identical to ft in problem 2, if you look again.
Last edited on
from all this I gather that you did not tell the complete truth. I don't think you do understand pointers, yet. But they do take a while to absorb :)

my quick explain to new programmers is this..
think of ram as a giant array of bytes.
eg
unsigned char ram[10000000000000000000000000000000000000000];
a pointer is an index into that, eg if you had this:
ram[123456] = 0xFF;

and if you think of it that way...

pointer p = 123456;

ram[p] is akin to *p and p[0] (same thing, 2 ways to write it), this is just syntax, and yes, its screwy.
and p is akin to an array index, here, its the pointless value 123456, it could be any location in the array though, which one isn't important to the human.

because ram is shared by the programs on the computer, it must be controlled to prevent 2 things messing with the same location in a bad way (you can share locations, but that's another topic for another day). You don't want the calculator overwriting your name in the word processor, do you? You have to use the new/delete syntax to request from the controller a piece of memory, and delete to give it back. That is just c++ syntax for the operating system interface to the shared memory hardware. If you take the address of something you already own, as in these examples using array names (you created the array and own it already), you don't need the new/delete interface. Two different uses of pointers really, one as a reference to something you already own, and one to a borrowed chunk of memory.
Last edited on
Hey, thanks very much jonnin. I need to study your comments in more detail, and then probably re-study them again. I know there's at least a couple of bits I don't get, but I'll work on understanding as much as I can and then jump back on here with the bits that still baffle me!
Okay; still struggling with understanding much of this. I get the bit about the unrolling of the 2D array, but I'll try and concentrate just on the first example problem for now, and worry about the rest of it once I have my head wrapped around the first one.

So, 1) *p=(char *)t;

Okay, so what are you actually naming this construct in your head? If it was simply "char *p", for example, I'd say it's "a pointer of char-type named p". But I don't know how to express in words what this "*p=(char *)t" is even creating.

Second; it seems a complicated way to create a pointer. Why can't one just say something like (pseudo-code) char *p=t;, where *p would presumably point to t[0][0]. And why the need to say "char" again; it was already declared as char at the beginning of the line.

You probably must think I'm as dumb as a rock, but in an effort to figure all this out I spent about three hours in B&N yesterday reading a chapter of a C++ book on pointers, and then looked at some more stuff online. Yeah, this hasn't clicked yet, but hopefully one day!

Anyway, as part of my investigation, I came across a Wiki page which gave an example of:

1
2
char *pc[10];           // array of 10 elements of 'pointer to char'
char (*pa)[10];         // pointer to a 10-element array of char 


So, ever the adventurer, I tried to incorporate this into a tiny little program to help me try and understand this pointer stuff, but everything I try ends up with segmentation errors (which, as I'd already learned, is probably related to the program trying to access memory space which it doesn't have access to):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main() {
   char *pc[10];            // array of 10 elements of 'pointer to char'
   char (*pa)[10];          // pointer to a 10-element array of char

   for (int x=0;x<10;x++)
      *pa[x]=x;

   for (int x=0;x<10;x++)
      std::cout << *pa[x];  // same seg fault using either *pa or pa.

return 0;
}


I'm obviously missing something entirely in this pointer conversation! Any [more] help appreciated.
Last edited on
Every pointer needs something to point at: either a named variable of the appropriate type (the first code below) or a bit of unnamed memory on the heap that is allocated with a "new" statement and to which you only have access through the pointer (the second code below).

In the first case, which is (in my opinion, anyway) a slightly unusual way to use pointers:

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

int main() {
   char *pc[10];            // array of 10 elements of 'pointer to char'
   char (*pa)[10];          // pointer to a 10-element array of char
   char pvals[10];          // you need something to point at

   for (int x=0;x<10;x++)
   {
      pvals[x]=(char)('0'+x);
      pc[x]=&pvals[x];         // the x-th pointer of pc points to the memory address of pvals[x]
   }
   
   pa = &pvals;                 // pa points to the memory address of 10-char array pvals
   
   for (int x=0;x<10;x++)
      std::cout << (*pa)[x];          // (*pa) IS pvals, so (*pa)[x] is pvals[x]
      
   std::cout << '\n';
   
   for (int x=0;x<10;x++)
      std::cout << *(pc[x]);          // pc[x] points to the xth element of pvals; *(pc[x]) is its value  
}



In the second case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int main() {
   char *pb;            // a char pointer
   
   pb = new char[10];   // 10-char array allocated on the heap and only addressable by this pointer

   for (int x=0;x<10;x++)
      pb[x]=(char)('0'+x);
   
   for (int x=0;x<10;x++)
      std::cout << pb[x];

   delete [] pb;      // I'd get told off if I didn't automatically include this
}
Last edited on
Okay, so what are you actually naming this construct in your head? If it was simply "char *p", for example, I'd say it's "a pointer of char-type named p". But I don't know how to express in words what this "*p=(char *)t" is even creating.

its name in my head is p.
its type in my head is char pointer.
it points to t, another variable created by the author of this stuff.

lets break the statement WAY down.
char *p; //this is what you really had. because they created multiple variables on one line, the char type is off to the side. char otherstufthatdidntmatter *p is what they have.

p = (char*)t; //assigns p a value using an existing variable.

so they lumped all that into one somewhat confusing statement to create it alongside another variable and initialize it all in one.


it exactly like

int x, y = (int) 3;

y's type is int.
y is assigned the value 3, which has a cast on it for no good reason.

the format and result are exactly the same thing, it just happens to be dealing with pointers instead of integers.

Second; it seems a complicated way to create a pointer. // it is!

Why can't one just say something like (pseudo-code) char *p=t;
t is not of type char*. Its a char**, actually, or a char *[], whatever … I think in assembly on this stuff and they are all just pointers to me but its 2 dimensional type will make the compiler angry.
you can say
char *p = t[0] though. This is just as ugly as what they did? /shrug?


You are not dumb. We see enough of that here to know the difference.
First, pointers take a bit of getting used to and secondly, this code stinks. It looks like the hybrid C/C++ style from the early 90s. I just happen to speak the dialect. As I already said, these are useful to see to stretch your head around the code but do not attempt to write code like this, its is poor.
Last edited on
Hey, thank you both (lastchance; jonnin) for your rapid replies. This'll take me a few days now to mull over what you've each explained. No doubt I'll be back on here with more questions, but thank you so much for your time and effort in trying to explain stuff. Some good Christmas reading for me!
Topic archived. No new replies allowed.