473,386 Members | 1,764 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Address within structure problem

Hi group,

I have an array of structure.
Say -
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 ans so
on...

I came at the following approach but it doesn't work. Could someone
please tell me the right way to do it.

Thanks.
#include <stdio.h>
#include <stdlib.h>
typedef struct Person {
int i;
int j;
int k;
}person;

person p[10]={{25, 2, 7},
{7, 3, 89},
{45, 56, 78}};
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 */
/* Incorrect pointer arithmetic */
for (i = 0; i < 3; i++) {
count += *((int *) addr);
addr += sizeof(person); /* This too ?? */
}
printf("%d", count);
}

Nov 14 '05 #1
5 1446
In article <11**********************@f14g2000cwb.googlegroups .com>,
Kelvin Moss <km**********@yahoo.com> wrote:
:I have an array of structure.

: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 ans so
:on...

If your structure is a fixed and small number of elements long, then
skip the type juggling and just do the manipulation by hand:

switch (offset) {
case 0:
for (i = 0; i < N_EL; i++ ) count += p[i].i;
break;
case 1:
for (i = 0; i < N_EL; i++ ) count += p[i].j;
break;
case 2:
for (i = 0; i < N_EL; i++ ) count += p[i].k;
break;
}

etc.. Notice this is barely longer than your original code
but without the dangers of getting the offsets wrong and
without having to do a bunch of address arithmetic.

You should reserve the type punning for instances where the
number of elements in the structure type is non-trivial or not
known ahead of time.

I would need to check the standard to see what it says
about alignment of values of the same kind. One could
imagine an architecture with a 6 byte int which was faster
to access when aligned on a 4 byte boundary; in such a case,
struct {int i, j, k;} could potentially have i start at offset 0,
j at offset 8, k at offset 16, whereas int [3] might be
offsets of 0, 6, 12. I do not recall what the standard says
about such matters.
--
When your posts are all alone / and a user's on the phone/
there's one place to check -- / Upstream!
When you're in a hurry / and propagation is a worry/
there's a place you can post -- / Upstream!
Nov 14 '05 #2

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
Nov 14 '05 #3

Arthur J. O'Dwyer wrote:
We could equivalently write

count += *(int *)it;
for (i=1; i < 10; ++i) {
it += size;
count += *(int *)it;
}
Thanks a lot. It works the way you have shown.

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.


True, the reason I wanted to do this juggling with pointer arithmetic
was that I had many members in my structure. For all of them I had to
do the same processing again and again.

switch (member_enum) {
case a:
for (i = 0; i < n; i++)
cnt += array[i].a
/* Some more procesing with arrayi].a
break;
case b:
/* same as case a but now with array[i].b */
break;
case c:
....

}

So I thought that may be I could write a generic routine to which I
could pass a pointer to member and deal all cases in a generic way.

Does this sound like a valid decision or do you think I should go with
the idiomatic solution ?

Thanks again.

Nov 14 '05 #4
Arthur J. O'Dwyer wrote:
We could equivalently write count += *(int *)it;
for (i=1; i < 10; ++i) {
Shouldn't this run only 9 times ?
it += size;
count += *(int *)it;
}


Nov 14 '05 #5

On Thu, 2 Mar 2005, Kelvin Moss wrote:
Arthur J. O'Dwyer wrote:
We could equivalently write

count += *(int *)it;
for (i=1; i < 10; ++i) {


Shouldn't this run only 9 times ?
it += size;
count += *(int *)it;
}


Yes. Nine iterations within the loop sum the elements from 'p[1].j'
to 'p[9].j'. The value of 'p[0].j' is added to 'count' by the line
immediately above the 'for' loop. So all ten items get counted, but
as "1+9" instead of "10." ;-)
(My original post pointed out why running the 'for' loop for ten
iterations was a Bad Idea: it would have invoked undefined behavior.)

-Arthur
Nov 14 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
by: dandelion | last post by:
Hi, Just another question for the standards jockeys... Suppose I have an Interrupt Vector Table located at address 0x0000 (16-bit machine). I want to dump the context of the IVT, by treating...
27
by: Adam Warner | last post by:
Hi all, In the code snippet below I successfully determine the address of val1:* struct o val1=l_SYM_2B(&a).o; print_aesthetic(&val1); The structure o is heavyweight. I understand...
5
by: Kevin Newman | last post by:
Does anyone know of any application (AJAX or other) that will display the appropriate address for for the selected (or detected) country? If not, does anyone know where I can find a list or...
0
by: seek help | last post by:
Hello, IDE: VS .NET 2003. Problem: Mangled bits of gc class embedded within native C++ class. Description: I have a gc class, BoxedInfo. This wraps a Value type structure, NotiInfo....
5
by: Steven Woody | last post by:
hi, i get a struct as below, typedef struct { uint16_t id; long offset; } foo_t;
2
by: ksarkar | last post by:
I have a problem regarding array of structures within a structure. I have an static array of structure within a structure eg. typedef struct { int x; }A; typedef struct { int...
1
by: 4Ankit | last post by:
Hey guys i am having some trouble with nesting one selection structure within another selection structure. At the moment i am unclear what selection structures are and just need a simple example of...
7
by: John Koleszar | last post by:
Hi all, I'm porting some code that provides compile-time assertions from one compiler to another and ran across what I believe to be compliant code that won't compile using the new compiler. Not...
36
by: Ajay | last post by:
Hi All, I got a segmentation fault while accessing a structure element. I pasted the output from gdb and the backtrace. However if I am able successfully access the structure using the...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.