On Thu, 2 Mar 2005, Kelvin Moss wrote:[indentation restored]
typedef struct Person {
int i;
int j;
int k;
} person;
person p[10]={{25, 2, 7},
{7, 3, 89},
{45, 56, 78}};
I am interested in processing all the first members of the struct in
the array together, all the second members of the struct together and
so on... i.e. i need to get {25, 7, 45}, {2, 3, 56} together [and] so
on...
I came at the following approach but it doesn't work. Could someone
please tell me the right way to do it.
[indentation restored]
size_t foo(void)
{
return offsetof(person, j);
}
int main()
{
int *struct_addr = NULL;
int addr;
int i;
int count = 0;
size_t offset;
offset = foo();
addr = &(p[0]) + offset; /* This seems wrong */
It is. Pointer arithmetic on structs works just the same as it does on
any type; that is, '&(p[0])' is equal to 'p', and thus '&(p[0])+offset'
is equal to '&p[offset]', which isn't valid unless the array 'p' has at
least 'offset' members.
And of course you can't assign that pointer value to an 'int'. You
should really try compiling your code before posting it, if you expect
people to give you any constructive feedback, instead of mostly parroting
the same stuff the compiler would have told you if you'd asked it.
Now, one thing which is conforming, as far as I know, would be the
following:
int main(void)
{
char *it = (char *)p + foo(); /* Address of p[0].j */
size_t size = sizeof *p; /* Size of each element */
int count = 0;
int i;
for (i=0; i < 10; ++i) {
count += *(int *)it;
if (i < 9)
it += size;
}
printf("%d\n", count);
return 0;
}
Notice the check on '(i < 2)' before we actually increment the pointer
'it'. That's very important, since if we didn't check that, we'd end
up incrementing 'it' past the end of the array 'p' and into Undefined
Behavior Land. Still, it's very clumsy, because we're checking 'i'
twice. We could equivalently write
count += *(int *)it;
for (i=1; i < 10; ++i) {
it += size;
count += *(int *)it;
}
But that's straying into "too clever for its own good" territory,
as far as I'm concerned.
Speaking of which... Why do you really want to do this? What's
wrong with the idiomatic solution,
int main(void)
{
int count = 0;
int i;
for (i=0; i < 10; ++i) {
count += p[i]->j;
}
printf("%d\n", count);
return 0;
}
It's shorter, much clearer, and almost certainly faster on any modern
optimizing compiler --- precisely /because/ it's shorter and clearer
and more idiomatic. Compiler writers have more incentive to optimize
this kind of loop than to optimize the icky, pointerful kind of loop
you were trying to demonstrate.
So I recommend the idiomatic solution, unless you're willing to
share a reason why you don't want to use it.
-Arthur