Maker Pro
Maker Pro

Passing an address to a function

Horn

Jun 4, 2012
42
Joined
Jun 4, 2012
Messages
42
I am wanting to pass multiple addresses to a function in c I have tried the following form.

deceleration
void FUNCTION(char &Var1[], char &Var2[][], int &Var3);

calling
FUNCTION( &Var1[], &Var2[][], &Var3)

Doing this allows me to modify the values in the function without having to return the values through the function. However I am getting syntax errors. I could use a few suggestions.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
It looks like you are confusing poinmters (addresses) and values.

In C, if you want to pass an adddress to a function, you declare e.g.:

void FUNCTION (char* test); /* *test is a character, so test alone is the address of the character */

Assuming the following declaratikon of the cvariable test within main:

main()
{
char test[100]; /* delcare char array test with 100 elements */
...

You can call


FUNCTION (test); /* test is the address of test[0] */

An example:

Code:
#define MAXCHAR 100

void FUNCTION (char* test);

int _tmain(int argc, _TCHAR* argv[])
{
	int i;

	char test[MAXCHAR];



	for (i=0;i<MAXCHAR;i++)
		test[i] = ' ';
	FUNCTION(test);
	std::cout << test[0];



	return 0;
}
void FUNCTION (char* test)
{
	int i;
	for (i=0;i<MAXCHAR;i++)
		*test++ = 'A';
	*(--test)= 0x00; /* end of string */
}

Or if your variable within the calling routine (main) is not declared as pointer, you get its address using the "&":

Code:
char test; /* declare test as single character */

FUNCTION (&test); /* call FUNCTION with the address of test as parameter */
Harald
 
Last edited:

Horn

Jun 4, 2012
42
Joined
Jun 4, 2012
Messages
42
I am getting a lot of illegal pointer to integer warnings on almost any combination of * and & I can make up and have scoured the internet and see that their are 1001 different ways to do this but they all "freeze up" my PIC. When I run the following code it does not even make it into main before freezing.

#include <pic.h>
#include <string.h>
#include <stdio.h>

#include "define.h"
//void CLEAR(uchar8 *Temp, uint8 STemp, uchar8 *Table, uint8 STable, uint8 *x, //uint8 *y, uint8 *v, uint8 *c, uint8 *ck)

main()
{
int x, y, v, c, ck, STemp, STable;
char Temp[30], Table[3][3];

STemp=sizeof(Temp);
STable=sizeof(Table);

CLEAR(Temp, STemp, Table, STable x, y, v, c, ck);


}

void CLEAR(uchar8 *Temp, uint8 STemp, uchar8 *Table, uint8 STable, uint8 *x, uint8 *y, uint8 *v, uint8 *c, uint8 *ck)
{
memset(*Temp, 0x20, STemp);
memset(*Table, 0x20, STable);
*x=0;
*y=1;
*v=2;
*c=0;
*ck=0;
}


Are their any obvious problems or possibly wiring issues?
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
1) the declaration s (data types) of your variables should match those in the function header. You mix data types:

declaration of variables:
int x, y, v, c, ck, STemp, STable;
char Temp[30], Table[3][3];

use in function header:
void CLEAR(uchar8 *Temp, uint8 STemp, uchar8 *Table, uint8 STable, uint8 *x, uint8 *y, uint8 *v, uint8 *c, uint8 *ck)

You should stick to one data type, e.g. either int or uint, but do not mix them. This would lead to:

void CLEAR(char *Temp, int STemp, char *Table, int STable, int *x, int *y, int *v, int *c, int *ck)

Which still isn't correct.

2) Let''s analyze this fragment:
void CLEAR(char *Temp, int STemp, char *Table, int STable, int *x, int *y, int *v, int *c, int *ck)
Since Temp is declared as
char Temp[30]
Temp (without * or &) is a pointer to the array. Therefore you can use Temp (without any qualifier) to submit the address of the array to the subroutine.
The same is true for Table.

x, y etc. are defined as:
int x, y, v, c, ck;
Therefore, in order to get the address of one of these variable you need to qualify the variable by the & sign:
address of x = &x
In the function header the syntax ... int *x... signifies that you will not handle the value of x, but its address. So this part of your code looks o.k.

In all, the code should like something like this:

main()
{...
CLEAR(Temp, STemp, Table, STable &x, &y, &v, &c, &ck);


...}
void CLEAR(char *Temp, int STemp, char *Table, int STable, int *x, int *y, int *v, int *c, int *ck)
{...}

I have two tips:
1) It may be easier to first get a grasp of the C syntax by using a C complier on the pC and get a feeling for the language. E.g. the free personal edition of Microsoft Visual Studio or GCC.
2) Using pointer (addresses) in C is rather easy, once you have understood the concept. However, even professionals time and again stumble over runtime errors caused by pointers that contain wrong or even illegal values. This can happen, for example, if you assign a value to a pointer without completely checking the validity of the value or if you do pointer arithmetic (increment, decrement are good candidates).
I therefore recommend that you deeply consider whether it is wise to use a pointer or if another, less critical method can do the job.

In your example, you could have
either:
- placed the short piece of code for nulling the arrays and variables into the main code. Unless you need this subroutine more than once, this will save you runtime overhead since no subroutine call needs to be performed.
or:
- made the arrays and the variables global variables. You can then access them by the subroutine without the need to handle pointers.

Every method has advantages and drawbacks. Which one prevails depends on the particular programming problem at hand.

Oh, and one very general tip: When you are dealing with a new situation in programing (e.g. syntax elements, data structures etc that are new to you) I suggest starting with very basic examples to get a grasp of the problem and its solution in the programming language used. In the above example, it would have been a good idea to start with justa single variable to learn the concepts of the * and & operator.
Here http://www.physics.drexel.edu/courses/Comp_Phys/General/C_basics/ is a tutorial on C programming (including pointers).

Harald
 

LordSputnik

Aug 11, 2011
45
Joined
Aug 11, 2011
Messages
45
Your original idea is fine. The problem is, that your using a strange combination of C++ and C.

In C++, the & operator, when used in a function declaration, indicates to the compiler that the value should be passed by reference. References are similar to pointers, but they always point to a valid address.

eg.
Code:
void a_function ( int & a )
{
a = 5;
}

int main()
{
int b = 0;
a_function(b);
/* Value of b is now 5, as we modified the value through a reference. */

return 0;
}

In C, there are no references, so to achieve the above, you'd use:

Code:
void a_function ( int* a )
{
(*a) = 5;
}

int main()
{
int b = 0;
a_function(&b);
/* Value of b is now 5, as we passed a pointer to the integer to a function, then dereferenced the pointer to modify the value that it points to. */

return 0;
}

You're trying to modify an array. An array is just a pointer to a block of memory. So, for example, an array of ints could be passed to a function taking a pointer to an int:

Code:
void a_function ( int* a )
{
(*a) = 5;
}

int main()
{
int b[10];
a_function(b);
/* Value of b[0] is now 5, as we passed a the array to a function, then dereferenced the pointer to modify the value that it points to. */

return 0;
}

So the value "pointed to" by an array is the first element of the array.

In your case, it looks like you want to pass an array, a 2D array and a variable to be modified in a function. To do this, you'd use this sort of code:

Code:
void a_function(char* a, char** b, int* c)
{
/* Do stuff here. For example: */
a[5] = 2;
b[1][3] = 6;
(*c) = 2;
}

int main()
{
char x[10];
char y[2][4];
int z = 0;

a_function(x, y, &z);
//Modifies x, y and z.

return 0;
}

I believe that this should work, although I haven't tested any of these samples, and it's been a few months since I last did any major C programming...

EDIT: Whenever you pass an array to a function, it's also good to pass in the dimensions of the array, so that you don't accidentally access memory you shouldn't. Eg.

Code:
void a_func(int* a, size_t b)
{
//Do stuff.
}

int main()
{
int x[10];
a_func(x, 10);
}
 
Last edited:

Horn

Jun 4, 2012
42
Joined
Jun 4, 2012
Messages
42
Harald you are right I read over the link you sent and I need to back down and open my visual studio again. I have used matlab too much. Also in my code I switched variable types to simplify my program and seems I forgot some, sorry. I have also tried what you recommended and it still throws warnings with the 2D array but works.

I tried your idea Lord Sputnik with the 2D array and it still throws the "illegal conversion between pointers" warning but it again works fine. As much as I hate to see warnings I may let this one slide for now and practice my knowledge of pointers on another project in visual studios and come back to tackle this at a later date.

Thank you both for the very helpful information. I am sorry to continue to bother you Harald! :)
 

LordSputnik

Aug 11, 2011
45
Joined
Aug 11, 2011
Messages
45
I read somewhere yesterday, you may need to explicitly state the number of columns:

Small example program, which compiles fine in gcc with no additional parameters:
Code:
#include <stdio.h>

void func( char (*p)[3] )
{
  int x, y;
  for( x = 0; x != 5; ++x )
  {
    for( y = 0; y != 3; ++y )
        printf("%i ",p[x][y]);
    
    putchar('\n');
  }
}

int main()
{
  char x[5][3] = {};
  func(x);
  
  return 0;
}
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
Sounds logical for a multidimensional array. How else should the compiler know that the argument is the address of a multidimensional array and not just a linear array?

Harald
 

Horn

Jun 4, 2012
42
Joined
Jun 4, 2012
Messages
42
and we have a winner! It is no longer throwing any warnings and is working properly. One question though, why? Do you happen to have that link or where you found it in a book?
 

Horn

Jun 4, 2012
42
Joined
Jun 4, 2012
Messages
42
That page contains a lot of information I need not just with the 2D array. Thank you very much Lord Sputnik!
 
Top