5
    typedef struct unit_class_struct {
        char *name;
    } person;



person * setName() {
       person * array;
       array = malloc (2 * sizeof(person));

       array->name = strdup("Robert");
       array++;
       array->name = strdup("Jose");
       return array;
}


    int main()
    {
        person *array;

        array = setName();

        printf("First name is %s\n", array[0].name);
        printf("Second name is %s\n", array[1].name);

        return 0;
    }

In this example, array[0].name returns Jose, not Robert as I expected, and array[1].name is empty.

However if I use

person * setName() {
       person * array;
       person * array_switch;
       array = malloc (2 * sizeof(person));
       array_switch = array;
       array_switch->name = strdup("Robert");
       array_switch++;
       array_switch->name = strdup("Jose");
       return array;
}

It works as expected. array.name[0] returns Robert and array.name[1] returns Jose.

Why does it require a second pointer for this example to work? Can I do it without using a second pointer AND still use pointer arithmetic?

I already know this is another way to do it as well:

person * setName() {
       person * array;
       array = malloc (2 * sizeof(person));
       array[0].name = strdup("Robert");
       array[1].name = strdup("Jose");
       return array;
}
2
  • What's wrong with accessing elements by index like array[1].name, again? Commented Nov 29, 2009 at 2:46
  • Nothing, I just already know how to do it, and I am trying to understand how to do it with pointer arithmetic Commented Nov 29, 2009 at 2:49

5 Answers 5

17

In your code:

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   array->name = strdup("Robert");
   array++;
   array->name = strdup("Jose");
   return array;
}

you allocate space for two elements in the array and set array to point to the first:

+-------+      +----------+
| array | ---> | array[0] |
+-------+      +----------+
               | array[1] |
               +----------+

You then increment the element pointer with array++ and that is what gets returned to the calling function at the end. That pointer points to the second array element which is why it seems to be wrong (and why you will almost certainly crash when you try to free that memory later by the way):

+-------+      +----------+
| array | -+   | array[0] |
+-------+  |   +----------+
           +-> | array[1] |
               +----------+

What you need is:

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   array[0].name = strdup("Robert");
   array[1].name = strdup("Jose");
   return array;
}

as you've already pointed out. This solution does not change the array pointer at all. But, if you really want to use pointers, you can just reverse the actions of the array++ with an array-- before returning so that array is set back to the right value:

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   array->name = strdup("Robert");
   array++;
   array->name = strdup("Jose");
   array--;
   return array;
}

Or, another way, which doesn't change the original pointer, doesn't use array indexing and doesn't use a second pointer is to use pointer arithmetic. The compiler knows what type the pointer points to so can adjust the pointer correctly to find the next element (you already know that it knows how to do this since array++ is shorthand for array = array + 1 and that statement adjusts the value by the correct amount also):

person * setName() {
   person * array;
   array = malloc (2 * sizeof(person));

   (array+0)->name = strdup("Robert");
   (array+1)->name = strdup("Jose");
   return array;
}
Sign up to request clarification or add additional context in comments.

Comments

2

You just do simple arithmetic pointer operations, like addition and subtraction, as well:

    array->name = "Robert";
    (array+1)->name = "Jose";
    return array;

Comments

1

A pointer is literally just a number (the address in memory). You're modifying this pointer to point somewhere else, and then returning it.

1 Comment

This is the answer, but is probably completely inscrutable to anyone who would be asking the question.
1

This will use pointer arithmetic, and preserve the original array pointer:

person * setName() {
       person * array;

       array = malloc (2 * sizeof(person));
       (array+0)->name = strdup("Robert");
       (array+1)->name = strdup("Jose");

       return array;
}

Comments

1

Yes


Since you incremented array, you no longer have a pointer to the [0] element, but a pointer to the [1] element. Do this:

   array->name = strdup("Robert");
   array++;
   array->name = strdup("Jose");
   return array - 1;

Keep in mind that in C p[x] is nothing more than *(p + x), or, if you like, and think about this one: (p + x)[0]. That last case is what your program was effectively doing, with x == 1. So (p + 1)[1] is the same as p[2], and there is nothing there, hence your null result.

(You can also write that as...

   array++->name = strdup("Robert");
   array--->name = strdup("Jose");
   return array;

...but if you do, a bunch of people will come along and downvote you. Was it really that hard to read? It is really our goal to write only uninspired clunky code?)

3 Comments

-1 for using an obscure construct like array++->name and array--->name
"Was it really that hard to read?" How could array--->name possibly be construed as easy to read?
I would think you guys would be happy that I fixed the main example to do it your way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.