Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

pass by reference quesion 1

Status
Not open for further replies.

blues77

Programmer
Jun 11, 2002
230
CA
I'm very new to C and i'm trying to implement a call by reference procedure. Basically i want to have a string passed to function to be modified and for this modification to be reflected in the main() function. Here's the program i have right now but i get the error.

gcc -Wall -pedantic -c test.c
test.c: In function `main':
test.c:13: warning: passing arg 1 of `printString' from incompatible pointer type
gcc -Wall -pedantic test.o -ll -o test

Can anyone tell me what's happening here and how to correct it. Here's my program

#include <stdio.h>
#include <stdlib.h>
#include &quot;test.h&quot;

int main()
{
char* p;
p = malloc(sizeof(char));

p = &quot;a&quot;;

printf(&quot;the pointer p conatins %s before calling printString\n&quot;, p);
printString(&p);
printf(&quot;Back in the main function p is %s\n&quot;, p);

return EXIT_SUCCESS;
}

void printString(char* s)
{
s = &quot;b&quot;;
printf(&quot;In the printString function the pointer p contains %s\n&quot;, s);
}



 
This is what you want...
[tt]
#include <stdio.h>
#include <stdlib.h>
//#include &quot;test.h&quot;

void printString(char *);

int main()
{
char* p;
p = malloc(sizeof(char));

* p = 'a';

printf(&quot;the pointer p points to a \&quot;%c\&quot; before calling printString\n&quot;,
*p);
printString(p);
printf(&quot;Back in the main function p points to a \&quot;%c\&quot;\n&quot;, *p);

return EXIT_SUCCESS;
}

void printString(char* s)
{
*s = 'b';
printf(&quot;In the printString function the pointer p points to a \&quot;%c\&quot;\n&quot;,
*s);
}
[/tt]
This causes the output...
[tt]
the pointer p points to a &quot;a&quot; before calling printString
In the printString function the pointer p points to a &quot;b&quot;
Back in the main function p points to a &quot;b&quot;
[/tt]
Your pointer [tt]p[/tt] is not storage, it is a pointer to storage. The [tt]malloc()[/tt] you call gets you the memory, and [tt]p[/tt] just points to it. SO, when you assign something to the memory, you have to assign it to where [tt]p[/tt] points to, or [tt]*p[/tt].

Also, you have only [tt]malloc[/tt]ed one byte (char), so you can't assign [tt]&quot;a&quot;[/tt] to it. This is actually a string consisting of a character [tt]a[/tt] and a null terminator (a zero value byte). The double quotes indicates a null terminated string, so always make sure you allow that extra byte of storage for it (or more). You CAN assign a single character though, which is what the [tt]'a'[/tt] is.

Hope this helps.

 
If you really wanted strings, and not just a pointer to a single character, it would be...
[tt]
#include <stdio.h>
#include <stdlib.h>
//#include &quot;test.h&quot;

void printString(char *);

int main()
{
char* p;
p = malloc(1000);

strcpy(p, &quot;Original&quot;);

printf(&quot;The pointer p points to \&quot;%s\&quot; before printString\n&quot;, p);
printString(p);
printf(&quot;Back in main, pointer p points to \&quot;%s\&quot;\n&quot;, p);

return EXIT_SUCCESS;
}

void printString(char* s)
{
strcpy(s, &quot;Modified!&quot;);
printf(&quot;In the printString function, pointer s points to \&quot;%s\&quot;\n&quot;, s);
}
[/tt]
Note that the malloc needs more memory allocated and we use the pointer differently because it's pointing to a string of characters and not just a single character.

Hope this helps.

 
I have one question. How come in your second example with the strings implemented you don't use a *p when printing out the value that the pointer points to:

Ex:
you wrote:
printf(&quot;The pointer p points to \&quot;%s\&quot; before printString\n&quot;, p);

how come it isn't:
printf(&quot;The pointer p points to \&quot;%s\&quot; before printString\n&quot;, *p);
 
Oh and one more thing.

Is this assignment correct


*p = &quot;hello&quot;;
instead of using strcpy
strcpy(p, &quot;hello&quot;);
 
Because when you have a [tt]%s[/tt] in the format string, the [tt]printf[/tt] will be looking for a pointer to a string to get the string to stick into the [tt]%s[/tt]'s place. The pointer [tt]p[/tt] is already a pointer, so you just give it the [tt]p[/tt].

When the [tt]%c[/tt] was in the format string, the [tt]printf[/tt] will be looking for a single character for the parameter, so you could give it either a hard coded [tt]'a'[/tt], or the single character that [tt]p[/tt] is pointing to by using [tt]*p[/tt].

Remember, since [tt]p[/tt] is a pointer, it is a variable that's value is a memory address, NOT the character. The [tt]malloc[/tt] you call gets you some memory, and returns the address of the memory that it got you. The variable [tt]p[/tt] just holds that memory address so we can use the memory assigned by the [tt]malloc[/tt].

In fact, try this...
[tt]
#include <stdio.h>
#include <stdlib.h>

int main()
{
char* p;
p = malloc(1000);

*p = 'a';

printf(&quot;The value of p is (in hex): %08X\n&quot;, p);
printf(&quot;The value p is pointing to is: %c\n&quot;, *p);
}
[/tt]
You get...
[tt]
The value of p is (in hex): 000209A0
The value p is pointing to is: a
[/tt]
Hope this helps.

 
Actually, no. The line...
[tt]
*p = &quot;Hello&quot;;
[/tt]
...is incorrect.

The construct of [tt]*p[/tt] is pointing to a single character, because of how you declared it ([tt]char * p;[/tt]). The variable [tt]p[/tt] is a pointer, but if you want it to point to a hard coded string, that is, have it hold the address of the start of that string, it would look like this...
[tt]
#include <stdio.h>
#include <stdlib.h>

int main()
{
char* p;

p = &quot;Hello&quot;;

printf(&quot;The value of p is (in hex): %08X\n&quot;, p);
printf(&quot;The value p is pointing to is: %s\n&quot;, p);
}
[/tt]
...giving the output...
[tt]
The value of p is (in hex): 000107C0
The value p is pointing to is: Hello
[/tt]
Why? Because we're saving the memory address of the first byte of the string in [tt]p[/tt]. Remember, since [tt]p[/tt] is a pointer, it doesn't hold a character, it doesn't hold a string of characters, it doesn't hold an int or a struct, or anything else we can point a pointer to. Since it's a pointer, it only holds a memory address. It's what's AT that memory address that is the character, or the string, or whatever.

That's why I took out the malloc. We're making [tt]p[/tt] point to a string constant and we weren't using the memory that [tt]malloc[/tt] got us.

Now, if we really wanted to use the memory we got from the malloc, then we do the following (same as in the example before)...
[tt]
char* p;
p = malloc(1000);

strcpy(p, &quot;Original&quot;);
[/tt]
...which means, declare a pointer, allocate some memory and save the address of that memory in the pointer, then copy this string to that memory that the pointer is pointing to. This way uses the memory we got from the call to [tt]malloc[/tt].

I think some of your confusion might be surrounding the double quoted string. Whenever you have a double quoted string in a program, you treat it the same as a pointer. (Huh?!?) When you have a double quoted string in a program, the compiler takes that explicit string (plus null terminating byte), and sets it in the executable, then uses the address of the string. So, when you have [tt]&quot;Hello&quot;[/tt] in your code, you actually have the memory address of where the compiler put the string. So, since you use it as a pointer, you can always assign a pointer to a pointer. That's why...
[tt]
p = &quot;Hello&quot;;
[/tt]
...works.

The single quotes, as it [tt]'a'[/tt] is a single byte containing the ASCII value for the letter a. It's not an address to it, it's the value (actually a decimal 97).

Hope this helps. (Hope I didn't muddy things too much).

 
Another thing, if we did the following...
[tt]
char * p;

p = malloc(1000);

p = &quot;Hello&quot;;
[/tt]
...it WOULD work, BUT first [tt]p[/tt] would be pointing to the memory that [tt]malloc[/tt] got us, then, [tt]p[/tt] would be pointing to the hard coded string [tt]&quot;Hello&quot;[/tt].

This would NOT copy the string to the memory we got from [tt]malloc[/tt]. [tt]p[/tt] would just be pointing to something else now and we would LOSE the memory that [tt]malloc[/tt] got us. It would still be allocated, but we wouldn't know where it is to use it. We put a different memory address in [tt]p[/tt], so we don't know the address of the memory that [tt]malloc[/tt] got us is any more.

To actually use that memory, you would leave the memory address in [tt]p[/tt] alone and copy your string to where it points by doing this...
[tt]
strcpy(p, &quot;Hello&quot;);
[/tt]
That way [tt]p[/tt] still holds the memory address of the memory we got from [tt]malloc[/tt], but we've copied something to that memory address. Look up the parameters that [tt]strcpy()[/tt] is expecting for why I used [tt]p[/tt] and not [tt]*p[/tt].

Hope this helps.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top