Log in

View Full Version : How to manipulate a variable value using an array?


amateurrobotguy
12-12-2007, 22:03
I really really really want to be able to use an array to call my relays. How can i do this? See below post for what i want to be able to do.

amateurrobotguy
12-12-2007, 22:14
Better yet, how can a store variable names within an array so that when i say:
myVar = 1;
array[1] = {myVar};

array[1] = 2;
printf(myVar);

I want the displayed output to be 2

Phil Mack
12-12-2007, 23:03
how can a store variable names within an array

You can store the address of the variable in the array, then use that address as a pointer to the value you want to print. Your array would be declared as an array of pointers.

myVar = 1;
array[1] = &myVar;

(*)(array[1]) = 2;
printf("%d\n",myVar);

Good luck,
~Phil

Tom Bottiglieri
12-12-2007, 23:38
Or use a macro.


#define MYVAR array[1]

print(MYVAR);

amateurrobotguy
13-12-2007, 00:11
I need you to confirm if what I am thinking is correct:

myVar = 1; Establish the "shell" as being = 1
array[1] = &myVar; Let the 1st value of array[] = the address of the "shell"

(*)(array[1]) = 2; the * means modify/check the contents of the address of myVar
printf(*myVar); since the shell wasn't updated, the * is needed to display the contents of the address of myVar since printf(myVar) would return 1

DanDon
13-12-2007, 01:01
I need you to confirm if what I am thinking is correct:

myVar = 1; Establish the "shell" as being = 1
array[1] = &myVar; Let the 1st value of array[] = the address of the "shell"

(*)(array[1]) = 2; the * means modify/check the contents of the address of myVar
printf(*myVar); since the shell wasn't updated, the * is needed to display the contents of the address of myVar since printf(myVar) would return 1

(*)(array[1]) = 2;

That would put a '2' in the memory cell pointed to by the address in array[1]. Or in this case....since the address in array[1] is that of myVar, the value of myVar would be 2, so assuming myVar is an int, your code for printing it out would be:

printf("%d\n",myVar);

Which would print out '2'.

amateurrobotguy
13-12-2007, 01:44
int *ptr;
int a, b;

a = 10;
ptr = &a;
b = *ptr;

Why bother with the int *ptr declaration when it has to be used again in the b= part? Is this just proper etiquette and not really needed?

Is this alright for my declaration:
int joystickbuttons[8] = {&p1_sw_trig, &p1_sw_top, &pl_sw_aux1, &p1_sw_aux2, &p2_sw_trig, &p2_sw_top, &p2_sw_aux1, &p2_sw_aux2};

And this for my looped search:
if ((*)joystickbuttons[arrayindexer[1]] == 1)

arrayindexer is just a simple array I am using for a counter.


If all this looks good then it means I finally figured this whole pointer thingie out largely thanks to this forum and Wiki.

Tom Bottiglieri
13-12-2007, 01:51
Why bother with the int *ptr declaration when it has to be used again in the b= part? This is the example from Wiki.


int *ptr; //ptr is a pointer to the address an 'int' somewhere in memory
int a, b; //compiler chooses where these go in memory, each have an address

a = 10; //set value of a to 10
//pass a by reference to ptr
ptr = &a; //ptr now holds the address of where a is in memory
b = *ptr; //b now holds the value (use *) that ptr points to

In this case, b would be equal to a at the end.
The first line declares a pointer, which is different from a regular variable.
You can do other cool things with this, too.


void idouble(int * input){
*input *= 2 ;
}

void main(){
int x ;
x = 5 ;
idouble(&x) ;
print(x);
}

This will print 10.

amateurrobotguy
13-12-2007, 01:54
So i have to say that my array of buttons is going to be holding addresses by declaring it like this:

int (*)joystickbuttons[8] = {&p1_sw_trig, &p1_sw_top, &pl_sw_aux1, &p1_sw_aux2, &p2_sw_trig, &p2_sw_top, &p2_sw_aux1, &p2_sw_aux2};

And thus the * in the declaration indicates that the variable is "special" in that it will indeed be holiding addresses and not just numbers and crap.

And the 2nd half of the above code:

if ((*)joystickbuttons[arrayindexer[1]] == 1)


Will my above 2 pieces of code work?

I don't get some of your example:


void idouble(int * input){ Input the address and convert it to the data "input"
*input += input ; I don't get the use of *input
}

void main(){
int x ;
x = 5 ;
idouble(&x) ; Call the above function giving it an address as a parameter
print(x); I don't get how the idouble() returns x
}

Tom Bottiglieri
13-12-2007, 02:23
I don't get some of your example:


void idouble(int * input){ Input the address and convert it to the data "input"
*input *= 2 ; I don't get the use of *input
}

void main(){
int x ;
x = 5 ;
idouble(&x) ; Call the above function giving it an address as a parameter
print(x); I don't get how the idouble() returns x
}

input is a pointer. it holds an address. in this particular case, it holds the address of x. putting a * in front of a pointer means that you want to look at the value held at the address of the pointer. if input = &x, *input = x. so modifying *input will actually be modifying the value held in x. (input is a pointer, so it has no real value attached to it.) By doing this, you can modify variables in your main function without returning ANYTHING from a called function. idouble returns nothing, but because you are telling it where x is in memory and not just the value of x, you can actually change x from another function. Make sense?

amateurrobotguy
13-12-2007, 02:27
Oh you sly bastard ;) You are basically bypassing the whole naming system of variables with input and directly puting data to addresses. I like this :) The int *input is just the declaration of input and not the actual conversion of &x to data....that was the confusing part. I can see why google refers to pointers as "advanced c".

Can you check the code i posted above the above post to tell me if that will work fine?

amateurrobotguy
13-12-2007, 20:13
This code isn't working:

int *joystickbuttons[8] = {&p1_sw_trig, &p1_sw_top, &pl_sw_aux1, &p1_sw_aux2, &p2_sw_trig, &p2_sw_top, &p2_sw_aux1, &p2_sw_aux2};

it errors me saying

I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1105] symbol 'pl_sw_aux1' has not been defined
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1101] lvalue required
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1218] extraneous initializer values

kevin.li.rit
13-12-2007, 20:31
Well I see you have a pl instead of a p1

amateurrobotguy
13-12-2007, 20:48
I fixed that but it still says

I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield
I:\Robot\2007\MPLAB\Current\2007_2005\user_routine s.c:411:Error [1200] cannot reference the address of a bitfield

kevin.li.rit
13-12-2007, 21:04
not a 100% but I think it may have something to do with the fact that the p1, p2 etc switches are defined to structures. They're defined in the C preprocessor but they were never declared as variables anywhere else(atleast not anywhere I could find)

I'm thinking that you can't do this with those variables...

lukevanoort
13-12-2007, 21:25
The problem is what MPLAB says it is, you cannot reference (aka have a pointer to) a bitfield, relay outputs and, I assume, joystick switch states are stored in bitfields.

amateurrobotguy
13-12-2007, 21:28
I know they are defined in ifi_aliases.h with the #define. So how do I get them out of bitfields? Do i need to "redeclare" them as ints?

lukevanoort
13-12-2007, 21:44
When I was trying to write a generalized, modular library for FRC robots (something like WPIlib, but not as high level), I ran into this same issue, but with relay outputs. My solution was to use a structure for storing the values then, at the end of the program loop, call a function that assigned the values in the structure to the actual relays. I think you could do something similar in your case; for example, you could just assign the values of the switches to the various variables in your array at the beginning of every program cycle.

kevin.li.rit
13-12-2007, 22:54
I know they are defined in ifi_aliases.h with the #define. So how do I get them out of bitfields? Do i need to "redeclare" them as ints?

I don't think you can redefine them to an INT since it's using a structure.

Phil Mack
13-12-2007, 23:29
cannot reference the address of a bitfield
Each of these names refers to a single bit, not a byte. Because each symbol is referring to a bit and not a byte, an address is insufficient to identify the symbol. The wikipedia article http://en.wikipedia.org/wiki/Bitfield explains the concept very well.

So how do I get them out of bitfields?
You must look to where the bit field is defined, and manipulate the struct. However, that seems somewhat counter to what you are attempting.

~Phil

amateurrobotguy
14-12-2007, 00:17
So much for elegant coding...

But i think lukevanoort's workaround will work, just as long as I put it all in a separate function. My goal with this was just to clean up a billion if-thens into a for loop but i guess a if-then function will make the code easier to read anyways.