Reputation: 79
Hi i'm studying pointers now. But while studying, I have a question and I want to ask
#include<stdio.h>
void store1(char **p){
char *tmp = "hello";
*p = tmp;
return;
}
void store2(char *p){
char *tmp = "hello";
p = tmp;
return;
}
int main(){
char *p;
//store1(&p, num);
store2(p);
printf("%s\n", p);
}
This is my questions Why does store1 function not have a segment fault and store2 function has a segment fault?
Why should we pass a variable of type char** as an argument to store a string?
If the char* type is passed as an argument, the char* tmp variable and the type match, so shouldn't it be stored in p?
Please let me know, smart brothers
Upvotes: 0
Views: 75
Reputation: 212424
store2(p)
does not change p
, so the value of p
in main remains uninitialized. The subsequent printf("%s\n", p);
thus invokes undefined behavior. (Indeed, I am not a language lawyer, but I'm pretty sure invoking store2(p)
when p is not initialized invokes UB.) In store1
, you pass the address of p
, and the call to store1
is able to modify the value of p
in main so that it now points to a string literal and the subsequent printf
is valid.
Here, I've re-written your code and changed some variable names to ease the discussion below:
#include<stdio.h>
void store1(char **a){ *a = "hello"; return; }
void store2(char *b){ b = "hello"; return; }
int
main(void)
{
char *p = NULL;
store2(p); /* After store2 returns, p is still NULL */
store1(&p); /* store1 assigns a value to p */
printf("%s\n", p);
}
In the above, b
is assigned the value NULL when store2
is called, but that value is never used. b
is effectively a local variable that is assigned the address of the string literal "hello", and that variable is discarded when store2
returns. However, a
is assigned the address of p
, and the assignment *a = "hello"
sets p
to the address of the string literal "hello".
Upvotes: 3
Reputation: 45674
C is (outside the preprocessor, which is its own horrible beast), strictly pass-by-value.
Thus, when one says "passing a variable" in reality one nearly always means "passing the value of a variable". Yes, sloppy speaking (and/or thinking) sinks projects.
In the rare cases "passing a variable" actually means what it says, that is emulated by "passing the address of a variable". Because it is so comparatively rare and the simpler phrase has been usurped, be explicit if that's what you mean.
Naturally, changing a copy has no effect on the source at all, nor does a copy reflect changes to the source after the fact.
Now you know why p
in main()
is still indeterminate after the call to store2()
, and why treating it as (a pointer to) a string causes Undefined Behavior.
Upvotes: 0
Reputation: 31409
Look here. I inlined the function:
int main(void)
{
char *p;
char *q;
q = p; // Pointless statment because q is overwritten
q = "hello"; // right here
puts(p);
}
Upvotes: 0