Go Down

### Topic: Taking the next big step.... Pointers!!! (Read 18033 times)previous topic - next topic

#### psfletcher

##### Dec 03, 2009, 04:23 pm
Hi,
I'm trying to setup a menu system, controlled via a struct.
Which i can then access, and the code know what parameter i want and how i want to display it.
I have the code working with a constant "2" which i can quite happily read.
What i want to be able to do is read a variable from the code,
ie counter or LEDON.  then have a routine point to that variable, read it and output it.
I have been told that points will help me, but i've tried playing with some examples but with no success!

Can anyone point me in the right direction please?
P.S. this is my first steps with pointers so wish me luck!

Pete

#### mfm9

#1
##### Dec 03, 2009, 08:24 pm
Pete,

I'm not sure what you're trying to do, but here are some pointer examples:
Code: [Select]
`void my_function(){    int sum;    add_numbers(1,2,&sum);    // &sum means a pointer to 'sum'    // at this point, 'sum' should have a value of 3.}void add_numbers(int num1,int num2,int *sum)// 'int *sum' means that the third parameter is a pointer to an integer{    *sum = num1 + num2;   // store the result in the int pointed to by 'sum'}`

Is that what you were looking for?

-Mike

#### psfletcher

#2
##### Dec 04, 2009, 02:19 pmLast Edit: Dec 04, 2009, 02:21 pm by psfletcher Reason: 1
Hi Mike,
Thanks for trying to help!
Your code works brilliantly but i can't get it to work with with the use of a struct which hopefully should hold the address of the variable, and when i come to print the variable out onto the serial port all i have to do is point to it.
But i dont know how to put the address into the struct and even more inportantly how to get it out!!!
The code below shows you what i am trying to do, the second variable record_type.two should ideally hold the variable address and in the main loop all i want to be able to do is point to it.
Does this make things a little clearer?
Thanks

Pete

Quote

// Parameters
typedef struct
{
char one[10];
int two;
int three;
}
record_type;
record_type record[8];
char inByte = 0;         // incoming serial byte

void setup(){
Serial.begin(9600);
record[3] = (record_type) {"data",5,9  };
establishContact();  // send a byte to establish contact until receiver responds

}
void loop(){

if (Serial.available() > 0) {
if (inByte == 'A'){
Serial.print(inByte);
//Serial.print(",");
for (int a=0; a<3; a++){
Serial.print(",");
Serial.print(record[a].one);
}
Serial.println();
}
{
if (inByte =='B'){
Serial.print(inByte);

for (int a=0; a<3; a++){
Serial.print(",");
Serial.print(record[a].one);
Serial.print(",");
Serial.print(record[a].two);
Serial.print(",");
Serial.print(record[a].three);
Serial.print(",");
}
Serial.println();
}
delay (1000);
}

}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.println("A");   // send an initial string
delay(300);
}
}

#### mfm9

#3
##### Dec 04, 2009, 04:32 pm
Pete,

Sorry, but I'm still not sure I understand why you want to use a pointer inside your struct.  Your code should work fine the way it stands.  There is a more conventional way to initialize the contents of your structure, though:
Code: [Select]
`typedef struct{  char one[10];  int two;  int three;}  record_type;record_type record[8] = {    {"ADC1",2,3},    {"ADC2",3,6},    {"ADC3",4,9},    {"data",5,9}    };`

If you want to have a pointer in a structure, you can declare it this way:
Code: [Select]
`typedef struct{  char one[10];  int *two;  int three;}  record_type;`But you'll also have to change the way you initialize it:
Code: [Select]
`record_type record[8] = {    {"ADC1",(int *)NULL,3},    {"ADC2",(int *)NULL,6},    {"ADC3",(int *)NULL,9},    {"data",(int *)NULL,9}    };`You could also initialize the pointers to point to global or static ints in your program, or you could fill in the pointers in your program.

You can also pass a pointer to the whole structure into a function.  Using your original structure, without any embedded pointers:
Code: [Select]
`typedef struct{  char one[10];  int two;  int three;}  record_type;record_type record[8] = {    {"ADC1",2,3},    {"ADC2",3,6},    {"ADC3",4,9},    {"data",5,9}    };void this_func(){    int i;    for (i = 0; i < 4; ++i)      that_func(&record[i]);}void that_func(record *r){    Serial.println(r->one);    Serial.println(r->two);    Serial.println(r->three);    r->two = r->two + 1;      // increment value of 'two' element}`Passing a pointer to a struct allows you to look at and change elements of that structure.  The notation "r->one" is shorthand for "(*r).one".

Regards,

-Mike

#### mfm9

#4
##### Dec 04, 2009, 04:32 pm
Pete,

Sorry, but I'm still not sure I understand why you want to use a pointer inside your struct.  Your code should work fine the way it stands.  There is a more conventional way to initialize the contents of your structure, though:
Code: [Select]
`typedef struct{  char one[10];  int two;  int three;}  record_type;record_type record[8] = {    {"ADC1",2,3},    {"ADC2",3,6},    {"ADC3",4,9},    {"data",5,9}    };`

If you want to have a pointer in a structure, you can declare it this way:
Code: [Select]
`typedef struct{  char one[10];  int *two;  int three;}  record_type;`But you'll also have to change the way you initialize it:
Code: [Select]
`record_type record[8] = {    {"ADC1",(int *)NULL,3},    {"ADC2",(int *)NULL,6},    {"ADC3",(int *)NULL,9},    {"data",(int *)NULL,9}    };`You could also initialize the pointers to point to global or static ints in your program, or you could fill in the pointers in your program.

You can also pass a pointer to the whole structure into a function.  Using your original structure, without any embedded pointers:
Code: [Select]
`typedef struct{  char one[10];  int two;  int three;}  record_type;record_type record[8] = {    {"ADC1",2,3},    {"ADC2",3,6},    {"ADC3",4,9},    {"data",5,9}    };void this_func(){    int i;    for (i = 0; i < 4; ++i)      that_func(&record[i]);}void that_func(record *r){    Serial.println(r->one);    Serial.println(r->two);    Serial.println(r->three);    r->two = r->two + 1;      // increment value of 'two' element}`Passing a pointer to a struct allows you to look at and change elements of that structure.  The notation "r->one" is shorthand for "(*r).one".

Regards,

-Mike

#### FrankM

#5
##### Dec 06, 2009, 04:20 pm
As far as I understand the OP he wants to be able to display the contents of a variable via a menu-system. The current examples all have fixed values (2,3,4,5).

I think what he is looking for is something like:

Code: [Select]
`// integer variables to be set and altered througout the codeint a=0;int b=0;// menurecord_type record[8] = {// first item: show a  { "Show A", &a, 3 }...`

The second part of the record structure should contain the address of the integer to show.

Regards,
Frank

#### psfletcher

#6
##### Dec 08, 2009, 01:57 pm
Hi Frank and Mike,
Out of interest how should i be defining the struct? int *A or just int A.

Thanks

Pete

#### FrankM

#7
##### Dec 09, 2009, 11:11 am
Since you want to store a pointer to an int: int *A. With int A you'd be creating an int itself.

#### psfletcher

#8
##### Dec 09, 2009, 12:13 pm
Hi Frank,
So i have amended the code, (I'm only using static variables at the moment to prove a point)

At the serial.print command, how should i be telling the compliar i want it to print out the value at this address?

This must be the last peice to the puzzle! - Made even more fun as i am using structs

Thanks

Pete

Code: [Select]
`// Parameters   typedef struct{  char one[10];  int *two;  int three;}  record_type;record_type record[8];char inByte = 0;         // incoming serial byteint num1 = 125;int num2 = 120;int num3 = 135;int num4 = 145;void setup(){  Serial.begin(9600);  record[0] = (record_type) {"ADC1",&num1,3  };  record[1] = (record_type) {"ADC2",&num2,6  };  record[2] = (record_type) {"ADC3",&num3,9  };  record[3] = (record_type) {"data",&num4,9  };  establishContact();  // send a byte to establish contact until receiver responds }void loop(){  if (Serial.available() > 0) {    inByte = Serial.read();        if (inByte == 'A'){      Serial.print(inByte);      //Serial.print(",");      for (int a=0; a<3; a++){        Serial.print(",");                Serial.print(record[a].one);      }      Serial.println();    }    {      if (inByte =='B'){        Serial.print(inByte);        for (int a=0; a<3; a++){            Serial.print(",");          Serial.print(record[a].one);          Serial.print(",");          Serial.print(record[a].two);          Serial.print(",");          Serial.print(record[a].three);          Serial.print(",");          }        Serial.println();      }      delay (1000);    }  }}void establishContact() {  while (Serial.available() <= 0) {    Serial.println("A");   // send an initial string    delay(300);  }}`

#### Groove

#9
##### Dec 09, 2009, 12:45 pm
To access what a pointer points to, you need to dereference the pointer, and the dereference operator is the asterisk '*'.

Thus, if you've got
Code: [Select]
`int a = 3;int* pa = &a;//////Serial.print (*pa);`

#### psfletcher

#10
##### Dec 09, 2009, 01:26 pm
Hi Groove,
I'm using a struct to hold the data and printing out the information from this struct
Code: [Select]
`Serial.print(record[a].two);`
How do i add * to this line to tell the serial.print command that it holds an address?
Thanks again!
Pete

#### Groove

#11
##### Dec 09, 2009, 01:43 pm
Code: [Select]
`Serial.print(*(record[a].two)); `

(I can never remember the association rules for pointers, so I always play safe and bracket)

#### psfletcher

#12
##### Dec 09, 2009, 02:24 pm
Cool thanks!
With the code i have above do you think i will have any problems with Null Pointers?
As the varaible are defined before they are used, i dont think i will, but a second opinion would be nice!
Thanks

Pete

#### Groove

#13
##### Dec 09, 2009, 02:55 pmLast Edit: Dec 09, 2009, 03:18 pm by GrooveFlotilla Reason: 1
Quote
With the code i have above do you think i will have any problems with Null Pointers

If you have null pointers and you dereference them, you will have problems. Always.
However, if you're certain you have initialised all the pointers, then you should be OK.

Don't forget, if you're worried about null pointers, you can always test for them, not so uninitialised ones!