7
#include <stdio.h>
#include <stdlib.h>

struct Point {
    double x;
};

void test(struct Point **a, int len)
{
    int i;

    printf("a = %p\n", a);
    for (i = 0; i < len; ++i)
        printf("%f\n", a[i]->x);
}

int main()
{
    int i;
    int len = 4;

    struct Point *P;

    P = malloc(len*sizeof(struct Point));

    for (i = 0; i < len; ++i) {
        P[i].x = i;
        printf("%f\n", P[i].x);
    }
    printf("&P = %p\n", &P);
    test(&P, len);

    return 0;
}

I am trying to pass an array of structs to a function (I want to pass a pointer to the array, not make a copy). When I try to use the array inside the function, I get an access violation. What is the correct way to do this? What am I doing wrong? a == &P, so it should work, right?

2
  • 1
    But P already is a pointer, it points to the first element of the allocated memory (the array). By passing the pointer, as is, you're not copying anything but the actual pointer. Commented May 7, 2015 at 14:35
  • 5
    printf("%f\n", (*a)[i].x); Commented May 7, 2015 at 14:36

5 Answers 5

5

Why's you want a struct Point **? You can rewrite the same as

void test(struct Point *a, int len)
{
   //some stuff
    printf("%f\n", a[i].x);

}

and call it like

 test(P, len);

This way, IMHO, the requirement

I want to pass a pointer to the array

is also met#.


(#) NOTE: To be strict, here we pass the pointer to the first element of the array, however, the behaviour compares equal. Thanks to Mr. @alk for the comment.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, So just to make sure, no copy is made when in the function, and any changes I make to the array still persist after the function returns?
To nitpick: The way you show a pointer to an array's 1st element is passed. This is different from a pointer to an array, the latter would be struct Point (*pa)[len].
@alk Very True sir. Can you suggest the appropriate wordings to modify my answer?
Although there is no benefit of using struct point ** , the only wrong in OP 's code is a[i]->x.
@haccks Right sir. IMHO, OP is much concerned about not make a copy part, rather than the data type itself. So, I just tried to put it in a simplified way. :-)
3

Passing &p to function test means that you are passing a pointer to the first element of an array of one element of type struct Point *. Therefore, only a[0] is valid (and hence a[0]->x) and all other a[i] are out of bound access. This will invoke undefined behavior.

Change a[i]->x to a[0][i].x or (*a)[i].x in test function.

Using pointer to pointer in this case is not worthy. This would be of worth using if passed pointer is to be modified in the function and that modification is expected to seen in the caller.

9 Comments

or better (*a)[i].x
@WojciechFrohmberg , Isn't it supposed to be what JoachimPileborg suggested in the above comment?
@CoolGuy if we have struct Point **a (*a) is dereference of a pointer [i] is reading the value from the address so basically also pointer dereference... this means after these two operations we get a type struct Point ergo: we cannot acces as we would get struct Point *...
@WojciechFrohmberg , I think you are right. So, Joachim's comment is wrong as he dereferences the pointer thrice?
@CoolGuy; Yes. I think he was confused then like me.
|
1

The array should be passed using the parameter struct Point *a. When you increment a the pointer will move by sizeof(struct Point).

void test(const struct Point *a, int len)
{
    ...
}

Comments

1

Other answers offer you better alternatives.But I'll put this here to help anyone (myself) understand why it is wrong.

enter image description here                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             

Comments

0

I want to pass a pointer to the array,

Taking your requirement literally you do it like this:

void test(size_t len, struct Point (*a)[len])
{
  size_t i;

  printf("a = %p\n", (void *) a);

  for (i = 0; i < len; ++i)
    printf("%f\n", (*a)[i].x);
}

And call it like this:

size_t len = 4;
struct Point * p = malloc(len * sizeof *p);

for (i = 0; i < len; ++i) {
    p[i].x = i;
    printf("%f\n", p[i].x);
}

printf("p = %p\n", (void *) p);
printf("&p = %p\n", (void *) &p);

test(len, &p);

You could also implement the same functionality (looping over the array's elements) by going the way proposed by Sourav Ghosh's answer. You then would pass a pointer to the array's 1st element then, but a pointer to the array itself.

Comments

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.