Ali  Z
Ali Z

Reputation: 47

passing a pointer to a structure as a parameter

I have a structure that I've set up, and a pointer to the structure, that is basically an array. I want to create a function that modifies specific values within the structure but can't seem to figure out how to pass in the structure pointer as a parameter.

struct deviations {
    int switch;
    int x;
    int y;
};

struct deviations *pdevs = malloc(24 * sizeof(int));

for(int i = 0; i < 8; i++) {
    (pdevs + i)->switchez = 1;
    (pdevs + i)->x = 0;
    (pdevs + i)->y = 0;
}

int top[3] = {0, 1, 2};
int bottom[3] = {5, 6, 7};
int left[3] = {0, 3 ,5};
int right[3] = {2, 4, 7};

for(int i = 0; i < 3; i++) {
   (pdevs + top[i])->y = -1; 
}

I have multiple (8) for loops like above and in each of them the basic structure is the same, except the array ("top"), lvalue ('y') and rvalue ('-1') change in each. I can't figure out how to declare a function with the structure/pointer to structure properly.

I currently have it around 26 lines of (8 for loops repeating) code and am pretty sure I can compress it down to a tidy little function if I can figure out how to pass in the pointer to the structure. Any help would be much appreciated!

This snippet is part of a larger function/program that determines whether or not to check the surrounding items (3 up top, 3 at bottom, one on each side). I have set up a structure with an on/off switch based on the position of the base item, and an x/y offset. I am trying to shift each individual cell by a certain amount +1/-1/ or 0 in the x or y position. And I am trying to flip the switch on or off depending on certain conditions about the x or y of the original cell. Malloc is probably unnecessary, but am unsure whether or not this array of structs will be used again later, if not, I will remove the call to malloc.

Thanks!

Upvotes: 0

Views: 90

Answers (2)

paddy
paddy

Reputation: 63481

This answer serves purely to challenge your thinking about your current approach.

Personally, unless there's some special logic involved, I would just ditch the loops completely and initialize your struct like this.

const struct deviations devs[8] = {
    { 1, -1, -1 },  // top-left
    { 1,  0, -1 },  // top
    { 1,  1, -1 },  // top-right
    { 1, -1,  0 },  // left
    { 1,  1,  0 },  // right
    { 1, -1,  1 },  // bottom-left
    { 1,  0,  1 },  // bottom
    { 1,  1,  1 }   // bottom-right
};

If you then decide that you really need to allocate that dynamically then you could just copy it:

struct deviations *pdevs = malloc(sizeof(devs));
if (pdevs) memcpy(pdevs, devs, sizeof(devs));

But if you really wanted to generate this stuff in a loop, why not something like this?

int ii = 0;
for(int y = -1; y <= 1; ++y) {
    for(int x = -1; x <= 1; ++x) {
        if (x == 0 && y == 0) continue;
        pdevs[ii].switch = 1;
        pdevs[ii].x = x;
        pdevs[ii].y = y;
        ++ii;
    }
}

Upvotes: 1

Barmar
Barmar

Reputation: 782509

So you want a generic function that can take an array of 3 indexes, the structure member to fill in, and the value.

The array and value are simple. To handle a structure member generically, you can use the offsetof() macro.

void fill_structs(struct deviations *pdevs, size_t offset, int indexes[3], int value) {
    for (int i = 0; i < 3; i++) {
        *((int *)((char *)&pdevs[indexes[i]] + offset)) = value;
    }
}

Then you call it like:

fill_structs(pdevs, offsetof(struct deviations, y), top, -1);

offsetof() returns the offset in bytes of a structure member from the base of the structure. So in the function you have to convert the address of the array element to char * so you can add the offset to it, then convert it to int * so you can dereference it and assign to the int member there.

BTW, you should get out of the habit of using things like

(pdevs + i) -> x

If you're using a pointer as the base of an array, use array syntax:

pdevs[i].x

It's much easier to tell that i is an array index this way.

Upvotes: 1

Related Questions