开发者

Difference between modifying a structure by reference versus other pointers

I am wondering why a structure pointer seems to be behave differently than a char pointer.

typedef struct person_struct {
    char *name;
} person;

changeStructName(person * name1) 
{
name1->name = "Robert";                       
}

changeCharName(char * name2) 
{
name2 = "Jose";                       
}

int main()
{
person * name1;
char * name2;

name1 = malloc(1 * sizeof(person));
changeStructName(name1);
changeCharName(name2);

printf("First name is %s\n",name1->name);
printf("Second name is %s\n",name2);
  }   

I know that using this code will work:

changeCharName(char ** name2) 
{
*name2 = "Jose";                       
}

changeCharName(&name2);

I am just curious why I do 开发者_JAVA百科not need to do the same pointer to pointer setup to the structure for it to be modified by reference?


In the first version of ChangeCharName you're modifying only a copy of the pointer, local to the function. The original value of name1 remains unchanged. Passing the pointer by reference (in the second version of the function) allows you to change the original (seen by main()) value of the pointer.


A pointer to a struct will allow you to modify the contents of that struct, but not which struct the pointer points to.


Remember that the -> operator is the same as (* ). - so this means your line:

name1->name = "Robert";

is the same as:

(*name1).name = "Robert";

...which looks a lot more like your alternate formulation for changeCharName, doesn't it?


Consider that the double-indirection that is explicit in char ** name2 is also present person * name1 because you've encapsulated a char * inside something else and then copied a pointer to that container. Therefore, when you dereference name1, you can access the char * that you wanted to change.


In your code, name1 is dereferenced but name2 is not. Try

(*name1).name = "Robert";

and

*name2 = "J";

and I hope you will see the parallels. Also, for this example to work, you will need to initialize name2 to point to some mutable storage. For example,

char *name2 = malloc(99);
strcpy(name2, "Rose");

then you will change "Rose" to "Jose".

I recommend you watch the video Pointer Fun with Binky.


Recall that C only passes parameters by value.

In your example,

changeCharName(char * name2)
{
  name2 = "Jose";
}

When you called changeCharName(), you passed the value contained in variable name2 in your main() procedure. (That value was in fact garbage, as you had never pointed name2 at anything.) When changeCharName() ran, it saved the passed value in a local temporary, then changed that local temporary to contain the address of a canned string. However, when changeCharName() returns, the (updated) local temporary goes the way of all temporary variables.

In your modified version, you instead passed in the ADDRESS of the local variable name2 in main(), and you wrote THROUGH that address to change the value stored in that local variable.

This is why Computer Science students take assembly language early in their careers, so they understand the real meaning of "address". It is also why FORTRAN, PASCAL, and Ada pass arguments by reference, and why BLISS made dereferencing an address an explicit operation.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜