Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #102281 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2017-01-21 08:52 -0800 |
| Last post | 2017-01-23 07:08 -0800 |
| Articles | 20 on this page of 55 — 11 participants |
Back to article view | Back to comp.lang.c
Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-21 08:52 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-21 09:35 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-21 10:28 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-21 23:49 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 00:29 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-22 10:54 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 03:28 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Keith Thompson <kst-u@mib.org> - 2017-01-22 07:44 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 08:24 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-22 10:43 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Keith Thompson <kst-u@mib.org> - 2017-01-22 12:22 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? BartC <bc@freeuk.com> - 2017-01-22 11:33 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-22 13:23 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? BartC <bc@freeuk.com> - 2017-01-22 13:28 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Keith Thompson <kst-u@mib.org> - 2017-01-22 07:47 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? BartC <bc@freeuk.com> - 2017-01-22 16:00 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? David Brown <david.brown@hesbynett.no> - 2017-01-22 18:23 +0100
Re: Optimizing the code: way to reduce if, else if-s within the loop? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-01-22 13:47 -0500
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-22 10:43 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-01-22 13:53 -0500
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-22 18:57 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? BartC <bc@freeuk.com> - 2017-01-22 19:18 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-22 21:54 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-23 02:41 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-23 11:20 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-23 03:53 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-23 12:12 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 03:24 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-22 13:16 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-22 07:47 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 08:16 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-01-22 11:54 -0500
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 11:23 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-22 11:08 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 22:19 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 22:41 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Robert Wessel <robertwessel2@yahoo.com> - 2017-01-23 02:17 -0600
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-23 02:16 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-23 03:59 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Keith Thompson <kst-u@mib.org> - 2017-01-23 08:44 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 08:23 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-22 07:52 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-22 08:17 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Richard Heathfield <rjh@cpax.org.uk> - 2017-01-23 17:11 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-23 10:35 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-23 10:38 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? BartC <bc@freeuk.com> - 2017-01-23 19:06 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Barry Schwarz <schwarzb@dqel.com> - 2017-01-23 14:31 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-23 21:31 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Alla _ <modelling.data@gmail.com> - 2017-01-24 01:56 -0800
Re: Optimizing the code: way to reduce if, else if-s within the loop? Manfred <noname@invalid.add> - 2017-01-24 14:38 +0100
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-24 13:57 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? BartC <bc@freeuk.com> - 2017-01-23 12:38 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-23 15:08 +0000
Re: Optimizing the code: way to reduce if, else if-s within the loop? m.labanowicz@gmail.com - 2017-01-23 07:08 -0800
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-22 18:57 +0000 |
| Message-ID | <87wpdmx6r0.fsf@bsb.me.uk> |
| In reply to | #102333 |
BartC <bc@freeuk.com> writes:
> On 22/01/2017 15:47, Keith Thompson wrote:
>> BartC <bc@freeuk.com> writes:
>>> On 22/01/2017 13:23, Ben Bacarisse wrote:
>>>> BartC <bc@freeuk.com> writes:
>> [...]
>>>>> This seems a common way of implementing it:
>>>>>
>>>>> #define offsetof(s,m) (int)&(((s *)0)->m)
>>>>
>>>> That would be wrong so I'm sorry to hear it's a common way.
>>>
>>> What's wrong with it?
>>
>> offsetof yields a result of type size_t. This macro yields a result of
>> type int. (It's also non-portable, but in a way that's likely to work
>> under most implementations.)
>
> Well, some use size_t in the cast, but this version came from a 32-bit
> compiler so was probably OK.
Given struct s { int i; }; then
assert(offsetof(struct s, i) - 1 > 0);
should never fire, but if offsetof yields an int it will.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-01-22 19:18 +0000 |
| Message-ID | <o630f6$gfa$1@dont-email.me> |
| In reply to | #102350 |
On 22/01/2017 18:57, Ben Bacarisse wrote:
> BartC <bc@freeuk.com> writes:
>
>> On 22/01/2017 15:47, Keith Thompson wrote:
>>> BartC <bc@freeuk.com> writes:
>>>> On 22/01/2017 13:23, Ben Bacarisse wrote:
>>>>> BartC <bc@freeuk.com> writes:
>>> [...]
>>>>>> This seems a common way of implementing it:
>>>>>>
>>>>>> #define offsetof(s,m) (int)&(((s *)0)->m)
>>>>>
>>>>> That would be wrong so I'm sorry to hear it's a common way.
>>>>
>>>> What's wrong with it?
>>>
>>> offsetof yields a result of type size_t. This macro yields a result of
>>> type int. (It's also non-portable, but in a way that's likely to work
>>> under most implementations.)
>>
>> Well, some use size_t in the cast, but this version came from a 32-bit
>> compiler so was probably OK.
>
> Given struct s { int i; }; then
>
> assert(offsetof(struct s, i) - 1 > 0);
>
> should never fire, but if offsetof yields an int it will.
The offset is zero.
IIUC, if you subtract one from that offset, the correct behaviour is for
that result to be greater than zero.
If zero minus one is <= zero, then that's wrong.
Okay....
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-22 21:54 +0000 |
| Message-ID | <87mveiwyjm.fsf@bsb.me.uk> |
| In reply to | #102352 |
BartC <bc@freeuk.com> writes:
> On 22/01/2017 18:57, Ben Bacarisse wrote:
>> BartC <bc@freeuk.com> writes:
>>
>>> On 22/01/2017 15:47, Keith Thompson wrote:
>>>> BartC <bc@freeuk.com> writes:
>>>>> On 22/01/2017 13:23, Ben Bacarisse wrote:
>>>>>> BartC <bc@freeuk.com> writes:
>>>> [...]
>>>>>>> This seems a common way of implementing it:
>>>>>>>
>>>>>>> #define offsetof(s,m) (int)&(((s *)0)->m)
>>>>>>
>>>>>> That would be wrong so I'm sorry to hear it's a common way.
>>>>>
>>>>> What's wrong with it?
>>>>
>>>> offsetof yields a result of type size_t. This macro yields a result of
>>>> type int. (It's also non-portable, but in a way that's likely to work
>>>> under most implementations.)
>>>
>>> Well, some use size_t in the cast, but this version came from a 32-bit
>>> compiler so was probably OK.
>>
>> Given struct s { int i; }; then
>>
>> assert(offsetof(struct s, i) - 1 > 0);
>>
>> should never fire, but if offsetof yields an int it will.
>
> The offset is zero.
>
> IIUC, if you subtract one from that offset, the correct behaviour is
> for that result to be greater than zero.
>
> If zero minus one is <= zero, then that's wrong.
>
> Okay....
I don't know what you mean by "wrong". You thought that offsetof being
int-valued would not matter on a 32-bit architecture. I'm just pointing
out that it does.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-23 02:41 -0800 |
| Message-ID | <f2707ec1-9d55-4f4c-8a88-98a38183f6d4@googlegroups.com> |
| In reply to | #102310 |
On Sunday, January 22, 2017 at 2:00:32 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
>
> > On Saturday, January 21, 2017 at 9:28:19 PM UTC+3, Barry Schwarz wrote:
> >> On Sat, 21 Jan 2017 08:52:25 -0800 (PST), Alla _
> >> <modelling.data@gmail.com> wrote:
> > <snip>
> >> Method 2: If your system supports the offsetof macro and if you
>
> A C implementation without offsetof is not conforming. It's a part of
> the language you can rely on being there.
>
> >> change some of the numeric members so they are all double, you could
> >> change method 1 to
> >> int offset;
> >> if(!strcmp(name, "Sales"))
> >> offset = offsetof(struct data, sales);
> >> else if (!strcmp(name, "Cost of Goods Sold") ||
> >> offset = offsetof(struct data, cs_cogs);
> >> etc
> >> and inside the loop you need only one assignment
> >> *(double*)((char*)dat_years + offset) = strtod(...);
> >>
> > <snip>
> > Reading some resources, I have found this phrase (repeated a few
> > times) on stackoverflow: "this code is not advised when using a modern
> > C compiler." Does it mean that it is not safe to use it, and that
> > this code will limit the usage of the program?
>
> It could mean that. It could also mean the writer is wrong. Equally,
> they could be correct but about slightly different code.
>
> > I still have to
> > dig much deeper into details, but I have saved those materials for
> > later study (I have to revisit the padding issue, etc, but I assume
> > offsetof() helps to avoid the padding - anyway, I would not like to
> > get into this topic now).
>
> Other than being a bit ugly there is nothing wrong with the code above
> and there is certainly no problem with padding.
>
> But I would go another way. Rather than find the offset of a named
> member, I'd make all the members have numbers and name the numbers.
> I.e. instead of
>
> struct data {
> double sales;
> double cs_cogs;
> ...
> };
>
> I'd write
>
> enum {
> Sales,
> CS_Cogs,
> ...
> NumberOfItems
> }; /* or use a list of #define lines */
>
> struct data {
> double item[NumberOfItems];
> };
>
> Now you can have the names in a table and simply look up the
> corresponding number.
>
> const char *names[] = {
> [Sales] = "Sales",
> [CS_Cogs] = "Cost of Goods Sold",
> ...
> };
I am doing my best to dig through this approach, and to learn
how to use it, and while doing it, I have realized that I can't use
it here because there are 3 names, each having two valid options;
so I can't create an array names and assign names to indices;
for example: [CS_Cogs] can be "Cost of Goods Sold" and
it also can be "COGS", which doesn't change the number of
input lines, only the name. Am I correct assuming that this
approach doesn't account for such issues?
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-23 11:20 +0000 |
| Message-ID | <87h94qvx8z.fsf@bsb.me.uk> |
| In reply to | #102363 |
Alla _ <modelling.data@gmail.com> writes:
> On Sunday, January 22, 2017 at 2:00:32 PM UTC+3, Ben Bacarisse wrote:
<snip>
>> But I would go another way. Rather than find the offset of a named
>> member, I'd make all the members have numbers and name the numbers.
<snip>
>> I'd write
>>
>> enum {
>> Sales,
>> CS_Cogs,
>> ...
>> NumberOfItems
>> }; /* or use a list of #define lines */
>>
>> struct data {
>> double item[NumberOfItems];
>> };
>>
>> Now you can have the names in a table and simply look up the
>> corresponding number.
>>
>> const char *names[] = {
>> [Sales] = "Sales",
>> [CS_Cogs] = "Cost of Goods Sold",
>> ...
>> };
> I am doing my best to dig through this approach, and to learn
> how to use it, and while doing it, I have realized that I can't use
> it here because there are 3 names, each having two valid options;
> so I can't create an array names and assign names to indices;
> for example: [CS_Cogs] can be "Cost of Goods Sold" and
> it also can be "COGS", which doesn't change the number of
> input lines, only the name. Am I correct assuming that this
> approach doesn't account for such issues?
Sorry, I did not spot that change. I was thinking of what you
originally said:
| (1) check if row names completely correspond to the required ones,
| no more or less of those - for this I assume I need an array
| of required row names, and when reading each line from the
| file, make sure that line 1 row name equals the first name in
| the array, etc.
I think at some point this changed to having two arrays of row names,
because I do remember seeing such a thing, but I'd forgotten it.
In my view, listing all the names in the code is messy enough that I
would put the names into a table, but when there are more than one valid
name that does gets a little more complicated. I suspect this is a case
of "too many cooks" again, so I think you should drop this idea an keep
going with a big "if" statement.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-23 03:53 -0800 |
| Message-ID | <42445523-fb0a-4f70-8b72-21ecf51a7410@googlegroups.com> |
| In reply to | #102367 |
On Monday, January 23, 2017 at 2:20:20 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
>
> > On Sunday, January 22, 2017 at 2:00:32 PM UTC+3, Ben Bacarisse wrote:
> <snip>
> >> But I would go another way. Rather than find the offset of a named
> >> member, I'd make all the members have numbers and name the numbers.
> <snip>
> >> I'd write
> >>
> >> enum {
> >> Sales,
> >> CS_Cogs,
> >> ...
> >> NumberOfItems
> >> }; /* or use a list of #define lines */
> >>
> >> struct data {
> >> double item[NumberOfItems];
> >> };
> >>
> >> Now you can have the names in a table and simply look up the
> >> corresponding number.
> >>
> >> const char *names[] = {
> >> [Sales] = "Sales",
> >> [CS_Cogs] = "Cost of Goods Sold",
> >> ...
> >> };
> > I am doing my best to dig through this approach, and to learn
> > how to use it, and while doing it, I have realized that I can't use
> > it here because there are 3 names, each having two valid options;
> > so I can't create an array names and assign names to indices;
> > for example: [CS_Cogs] can be "Cost of Goods Sold" and
> > it also can be "COGS", which doesn't change the number of
> > input lines, only the name. Am I correct assuming that this
> > approach doesn't account for such issues?
>
> Sorry, I did not spot that change. I was thinking of what you
> originally said:
>
> | (1) check if row names completely correspond to the required ones,
> | no more or less of those - for this I assume I need an array
> | of required row names, and when reading each line from the
> | file, make sure that line 1 row name equals the first name in
> | the array, etc.
>
> I think at some point this changed to having two arrays of row names,
> because I do remember seeing such a thing, but I'd forgotten it.
>
> In my view, listing all the names in the code is messy enough that I
> would put the names into a table, but when there are more than one valid
> name that does gets a little more complicated. I suspect this is a case
> of "too many cooks" again, so I think you should drop this idea an keep
> going with a big "if" statement.
All right. Thank you very much. Can I ask you for a great favor (yes, yet
another one)? Could you, please, records what you written above and
can we, when I am done with this program, do some exercises on this
approach so I can learn it? Including extended and more complicated
versions when there might be a few valid names (we can take my
program as an example for a simple case - because there are only
3 names, and each of those has only 2 valid versions)?
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-23 12:12 +0000 |
| Message-ID | <87bmuyvutr.fsf@bsb.me.uk> |
| In reply to | #102368 |
Alla _ <modelling.data@gmail.com> writes: > On Monday, January 23, 2017 at 2:20:20 PM UTC+3, Ben Bacarisse wrote: <snip> >> In my view, listing all the names in the code is messy enough that I >> would put the names into a table, but when there are more than one valid >> name that does gets a little more complicated. I suspect this is a case >> of "too many cooks" again, so I think you should drop this idea an keep >> going with a big "if" statement. > All right. Thank you very much. Can I ask you for a great favor (yes, yet > another one)? Could you, please, records what you written above and > can we, when I am done with this program, do some exercises on this > approach so I can learn it? Including extended and more complicated > versions when there might be a few valid names (we can take my > program as an example for a simple case - because there are only > 3 names, and each of those has only 2 valid versions)? Sure. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-22 03:24 -0800 |
| Message-ID | <2e2405b7-23f8-4572-b71f-f4011e1bc284@googlegroups.com> |
| In reply to | #102295 |
On Saturday, January 21, 2017 at 9:28:19 PM UTC+3, Barry Schwarz wrote:
> On Sat, 21 Jan 2017 08:52:25 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
>
<snip>
>
> Method 2: If your system supports the offsetof macro and if you
> change some of the numeric members so they are all double, you could
> change method 1 to
> int offset;
> if(!strcmp(name, "Sales"))
> offset = offsetof(struct data, sales);
> else if (!strcmp(name, "Cost of Goods Sold") ||
> offset = offsetof(struct data, cs_cogs);
> etc
> and inside the loop you need only one assignment
> *(double*)((char*)dat_years + offset) = strtod(...);
>
<snip>
Below are a few issues I face when trying to implement the offsetof():
(1) I have created a separate function to find the offset value;
I use fprintf for debugging purposes in this function; the function's
prototype: int find_struct_member(char *name);
I don't get any expected result. The structure is not populated, but
there are a few more issues. I am sure I do something wrong; I have
tried to find the mistake, but I don't yet see it. Also (double) cast
is not allowed by compiler because struct members all have
double type.
The problem I see is that the first value of the offset I get is 8, but
I presume it should be 4: the first member of struct data is int
(those are years), and all other members are of type double.
sizeof(int) on my computer is 4, double is 8. All offsets I get
are 8.
Here is the struct's typedef (it's before the main function):
typedef struct data {
int year;
double sales;
double cs_cogs;
double cs_gross_profit;
double cs_sga;
double cs_oper_inc;
double cs_dep_amor;
double cs_oper_prof;
double cs_int_exp;
double cs_gain_loss;
double cs_pretax_inc;
double cs_tax_exp;
double cs_net_inc;
} data;
As this is before the main function, I don't need to pass
a pointer to data when I call find_struct_member function;
I pass only the name. The find_struct_member function
is called within the process_line function (see (2) below):
/** Function to determine a particular struct member **/
int find_struct_member(char *name)
{
int offset;
if(!strcmp(name, "Sales"))
{
offset = offsetof(struct data, sales);
fprintf(stderr, "offset sales %i\n", offset);
}
else if (!strcmp(name, "Cost of Goods Sold") ||
!strcmp(name, "COGS") )
{
offset = offsetof(struct data, cs_cogs);
fprintf(stderr, "offset cs_cogs %i\n", offset);
}
else if(!strcmp(name, "Gross Profit"))
{
offset = offsetof(data, cs_gross_profit);
fprintf(stderr, "offset cs_gross_profit %i\n", offset);
}
else if (!strcmp(name, "\"Selling, General, and Admin Exp\"") ||
!strcmp(name, "SG&A") )
{
offset = offsetof(data, cs_sga);
fprintf(stderr, "offset cs_sga %i\n", offset);
}
else if (!strcmp(name, "Operating Income before Depr") ||
!strcmp(name, "Operating Income before Depreciation") )
{
offset = offsetof(data, cs_oper_inc);
fprintf(stderr, "offset cs_oper_inc %i\n", offset);
}
else if(!strcmp(name, "Depreciation and Amortization"))
{
offset = offsetof(data, cs_dep_amor);
fprintf(stderr, "offset cs_dep_amor %i\n", offset);
}
else if(!strcmp(name, "Operating Profit"))
{
offset = offsetof(data, cs_oper_prof);
fprintf(stderr, "offset cs_oper_prof %i\n", offset);
}
else if(!strcmp(name, "Interest Expense"))
{
offset = offsetof(data, cs_int_exp);
fprintf(stderr, "offset cs_int_exp %i\n", offset);
}
else if(!strcmp(name, "Other Gains and Losses"))
{
offset = offsetof(data, cs_gain_loss);
fprintf(stderr, "offset cs_gain_loss %i\n", offset);
}
else if(!strcmp(name, "Pretax Income"))
{
offset = offsetof(data, cs_pretax_inc);
fprintf(stderr, "offset cs_pretax_inc %i\n", offset);
}
else if(!strcmp(name, "Income Tax Expense"))
{
offset = offsetof(data, cs_tax_exp);
fprintf(stderr, "offset cs_tax_exp %i\n", offset);
}
else if(!strcmp(name, "Net Income"))
{
offset = offsetof(data, cs_net_inc);
fprintf(stderr, "offset cs_net_inc %i\n", offset);
}
else
return -1;
return offset;
}
(2) the function process_line () is called within the main function,
and here is this function's prototype:
bool process_line (FILE *input_file, data *dat_years, assumptions *rates);
(3) and then within process_line() the program calls find_struct_member(name),
passing the pointer to the name.
(4) after that the process_line() calls parse_numbers function to populate the
structure;
/** Function to parse numbers from each line **/
bool parse_numbers(char *line, int offset, data *dat_years)
{
char *ptr = line;
char *not_converted = ptr;
int count = 0;
//DEBUG
fprintf(stderr, "Offset passed to function %i\n", offset);
while(count < DATA_SIZE)
{
*((char*)dat_years + offset) = strtod(ptr, ¬_converted);
if (not_converted > ptr)
{
count++;
dat_years += (count != DATA_SIZE);
ptr = not_converted + (*not_converted != '\0');
}
else
{
fprintf(stderr, "Incorrect data on line %s at count %i\n", line, count);
return false;
}
}
return count == DATA_SIZE;
}
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-22 13:16 +0000 |
| Message-ID | <87k29nxmit.fsf@bsb.me.uk> |
| In reply to | #102312 |
Alla _ <modelling.data@gmail.com> writes:
<snip>
> Below are a few issues I face when trying to implement the offsetof():
I'll explain the problem but you really should do this another way.
<snip>
> Here is the struct's typedef (it's before the main function):
> typedef struct data {
> int year;
> double sales;
> double cs_cogs;
> double cs_gross_profit;
> double cs_sga;
> double cs_oper_inc;
> double cs_dep_amor;
> double cs_oper_prof;
> double cs_int_exp;
> double cs_gain_loss;
> double cs_pretax_inc;
> double cs_tax_exp;
> double cs_net_inc;
> } data;
<snip>
> /** Function to determine a particular struct member **/
> int find_struct_member(char *name)
> {
> int offset;
> if(!strcmp(name, "Sales"))
> {
> offset = offsetof(struct data, sales);
> fprintf(stderr, "offset sales %i\n", offset);
> }
> else if (!strcmp(name, "Cost of Goods Sold") ||
> !strcmp(name, "COGS") )
> {
> offset = offsetof(struct data, cs_cogs);
> fprintf(stderr, "offset cs_cogs %i\n", offset);
> }
> else if(!strcmp(name, "Gross Profit"))
> {
> offset = offsetof(data, cs_gross_profit);
> fprintf(stderr, "offset cs_gross_profit %i\n", offset);
> }
> else if (!strcmp(name, "\"Selling, General, and Admin Exp\"") ||
> !strcmp(name, "SG&A") )
> {
> offset = offsetof(data, cs_sga);
> fprintf(stderr, "offset cs_sga %i\n", offset);
> }
> else if (!strcmp(name, "Operating Income before Depr") ||
> !strcmp(name, "Operating Income before Depreciation") )
> {
> offset = offsetof(data, cs_oper_inc);
> fprintf(stderr, "offset cs_oper_inc %i\n", offset);
> }
> else if(!strcmp(name, "Depreciation and Amortization"))
> {
> offset = offsetof(data, cs_dep_amor);
> fprintf(stderr, "offset cs_dep_amor %i\n", offset);
> }
> else if(!strcmp(name, "Operating Profit"))
> {
> offset = offsetof(data, cs_oper_prof);
> fprintf(stderr, "offset cs_oper_prof %i\n", offset);
> }
> else if(!strcmp(name, "Interest Expense"))
> {
> offset = offsetof(data, cs_int_exp);
> fprintf(stderr, "offset cs_int_exp %i\n", offset);
> }
> else if(!strcmp(name, "Other Gains and Losses"))
> {
> offset = offsetof(data, cs_gain_loss);
> fprintf(stderr, "offset cs_gain_loss %i\n", offset);
> }
> else if(!strcmp(name, "Pretax Income"))
> {
> offset = offsetof(data, cs_pretax_inc);
> fprintf(stderr, "offset cs_pretax_inc %i\n", offset);
> }
> else if(!strcmp(name, "Income Tax Expense"))
> {
> offset = offsetof(data, cs_tax_exp);
> fprintf(stderr, "offset cs_tax_exp %i\n", offset);
> }
> else if(!strcmp(name, "Net Income"))
> {
> offset = offsetof(data, cs_net_inc);
> fprintf(stderr, "offset cs_net_inc %i\n", offset);
> }
> else
> return -1;
> return offset;
> }
This is the sort of ode that should be setting of alarm bells.
Computers should do the repetitive things not programmers. These values
should be an array with named indexes (as per my other post).
<snip>
> /** Function to parse numbers from each line **/
> bool parse_numbers(char *line, int offset, data *dat_years)
> {
> char *ptr = line;
> char *not_converted = ptr;
> int count = 0;
>
> //DEBUG
> fprintf(stderr, "Offset passed to function %i\n", offset);
>
> while(count < DATA_SIZE)
> {
> *((char*)dat_years + offset) = strtod(ptr, ¬_converted);
You are trying to to store a double in a char. You can get most
compiler to warn you that this conversion is likely to loose a lot of
information.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2017-01-22 07:47 -0800 |
| Message-ID | <lek98c5a6hdnpe9ppspo3vfa2uss7kun38@4ax.com> |
| In reply to | #102312 |
On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:
> *((char*)dat_years + offset) = strtod(ptr, ¬_converted);
Here is the line of code I suggested
*(double*)((char*)dat_years + offset) = strtod(...);
You chose to leave out a significant piece, apparently thinking it
didn't matter. Now you need to explain to yourself why both cast
operators are essential AND why they are placed where they are. Ben
has already explained what happens when you omit the first one. What
would happen you omitted the second? What would happen if you moved
the second outside the parenthetical expression? What would happen if
you omitted both?
Copying code others generate is stenography. Programming requires you
to understand what the code is doing.
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-22 08:16 -0800 |
| Message-ID | <ff4c53b2-24d0-4497-999c-8239d2b160e6@googlegroups.com> |
| In reply to | #102328 |
On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote: > On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _ > <modelling.data@gmail.com> wrote: > > > *((char*)dat_years + offset) = strtod(ptr, ¬_converted); > > Here is the line of code I suggested > *(double*)((char*)dat_years + offset) = strtod(...); > > You chose to leave out a significant piece, apparently thinking it > didn't matter. Now it's my time to grumble )))) I didn't leave out that "significant piece, apparently (I wish you didn't use this word - it did make things worse) thinking it didn't matter" = wrong. I have mentioned *why* it is not in my code. I usually don't highlight things, because it is a rather bad manner, but sometimes even I get tired of groundless accusations - my compiler didn't allow me to use double casting because all values already are of double type. Reading now all the rest of the comment, and trying to fix the problem based on explanations, suggested by Ben. >Now you need to explain to yourself why both cast > operators are essential AND why they are placed where they are. Ben > has already explained what happens when you omit the first one. What > would happen you omitted the second? What would happen if you moved > the second outside the parenthetical expression? What would happen if > you omitted both? > > Copying code others generate is stenography. Programming requires you > to understand what the code is doing. > > -- > Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-01-22 11:54 -0500 |
| Message-ID | <c6f07dd8-1293-084e-3b5d-06e631a55532@verizon.net> |
| In reply to | #102334 |
On 01/22/2017 11:16 AM, Alla _ wrote:
> On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote:
>> On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _
>> <modelling.data@gmail.com> wrote:
>>
>>> *((char*)dat_years + offset) = strtod(ptr, ¬_converted);
>>
>> Here is the line of code I suggested
>> *(double*)((char*)dat_years + offset) = strtod(...);
>>
>> You chose to leave out a significant piece, apparently thinking it
>> didn't matter.
> Now it's my time to grumble )))) I didn't leave out that "significant piece,
> apparently (I wish you didn't use this word - it did make things worse)
> thinking it didn't matter" = wrong. ...
> ... I have mentioned *why*
> it is not in my code. ...
I believe you're referring to the comment: "Also (double) cast
is not allowed by compiler because struct members all have
double type." The type of the members is completely irrelevant to the
validity of that cast, because there is no use of any of those members
anywhere near the cast. Note also that it's a (double*) cast, not a
(double) cast. If you miscopied Barry's code as follows:
*(double)((char*)dat_years + offset) = strtod(...);
then the compiler should complain about the fact that you're trying to
convert a char* value to a double, and then trying to apply the unary *
operator to a value of type double. However, that's not because of any
problem with members having double type.
> ... I usually don't highlight things, because it is
> a rather bad manner, but sometimes even I get tired of groundless
> accusations - my compiler didn't allow me to use double casting
Any compiler which objects to the correct version of the code that Barry
provided is not a conforming implementation of C. I strongly suspect
that what it objected to is something significantly different from
Barry's code. If you could, would you provide the exact text of a
minimal program containing only that code, and just enough other code to
define the things used in that code, and the error messages you get when
you compile it?
> because all values already are of double type.
All values? None of the following values has double type:
dat_years data*
(char*)dat_years char*
offset int
(char*)dat_year+offset char*
*((char*)dat_year+offset) char
The most important case is that last one - the fact that it does not
have double type is the reason your code is wrong, and is also the
reason why Barry's code contains the cast to (double*).
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-22 11:23 -0800 |
| Message-ID | <2ca07851-ea87-4c02-8d9b-a67114f04496@googlegroups.com> |
| In reply to | #102338 |
On Sunday, January 22, 2017 at 7:55:02 PM UTC+3, James R. Kuyper wrote: > On 01/22/2017 11:16 AM, Alla _ wrote: > > On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote: > >> On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _ > >> <modelling.data@gmail.com> wrote: > >> > >>> *((char*)dat_years + offset) = strtod(ptr, ¬_converted); > >> > >> Here is the line of code I suggested > >> *(double*)((char*)dat_years + offset) = strtod(...); > >> > >> You chose to leave out a significant piece, apparently thinking it > >> didn't matter. > > Now it's my time to grumble )))) I didn't leave out that "significant piece, > > apparently (I wish you didn't use this word - it did make things worse) > > thinking it didn't matter" = wrong. ... > > > ... I have mentioned *why* > > it is not in my code. ... > > I believe you're referring to the comment: "Also (double) cast > is not allowed by compiler because struct members all have > double type." The type of the members is completely irrelevant to the > validity of that cast, because there is no use of any of those members > anywhere near the cast. Note also that it's a (double*) cast, not a > (double) cast. If you miscopied Barry's code as follows: > > *(double)((char*)dat_years + offset) = strtod(...); > > then the compiler should complain about the fact that you're trying to > convert a char* value to a double, and then trying to apply the unary * > operator to a value of type double. However, that's not because of any > problem with members having double type. Yes, that's exactly what happened. I can't find any plausible reason why I made that typo - I was absolutely sure I use (double*), and therefore before coming here I spent over 2,5 hours searching the net for possible reasons and reading different material, rewriting the code, and not understanding what could go wrong. Apologies! I have heard that even professionals can miss these sort of typos; though this doesn't justify my mistake at all. > > > ... I usually don't highlight things, because it is > > a rather bad manner, but sometimes even I get tired of groundless > > accusations - my compiler didn't allow me to use double casting > > Any compiler which objects to the correct version of the code that Barry > provided is not a conforming implementation of C. I strongly suspect > that what it objected to is something significantly different from > Barry's code. If you could, would you provide the exact text of a > minimal program containing only that code, and just enough other code to > define the things used in that code, and the error messages you get when > you compile it? > > > because all values already are of double type. > > All values? None of the following values has double type: > dat_years data* > (char*)dat_years char* > offset int > (char*)dat_year+offset char* > *((char*)dat_year+offset) char > > The most important case is that last one - the fact that it does not > have double type is the reason your code is wrong, and is also the > reason why Barry's code contains the cast to (double*).
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2017-01-22 11:08 -0800 |
| Message-ID | <0lv98clfgb14i3nidh80crekhsst6uehps@4ax.com> |
| In reply to | #102334 |
On Sun, 22 Jan 2017 08:16:07 -0800 (PST), Alla _ <modelling.data@gmail.com> wrote: >On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote: >> On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _ <snip> >> Here is the line of code I suggested >> *(double*)((char*)dat_years + offset) = strtod(...); >> >> You chose to leave out a significant piece, apparently thinking it >> didn't matter. >Now it's my time to grumble )))) I didn't leave out that "significant piece, >apparently (I wish you didn't use this word - it did make things worse) >thinking it didn't matter" = wrong. I have mentioned *why* >it is not in my code. I usually don't highlight things, because it is >a rather bad manner, but sometimes even I get tired of groundless >accusations - my compiler didn't allow me to use double casting >because all values already are of double type. Yes, you did say this and it still makes no sense. The compiler may know you are attempting to store into the structure but it has no idea of which member. Especially since this is in a different function than the one that computed offset. The parenthetical expression has type char*. It is legal (but not usually meaningful) to cast this value to double. However, once you do that, you are not allowed to dereference the result of that operation. That is a constraint violation that has nothing to do with the types of the members in your structure. There is no cast to double in my suggestion. There is a cast to double*. Since the operand of that cast is a pointer to an object type, there is no syntax constraint on casting the value to a pointer to a different object type. The result may be implementation dependent (or even undefined) but that is a different issue. If your compiler actually complained about a cast to double* (as opposed to double as you stated), we would very much like to see THAT code and the resulting diagnostic. If the problem is that you left off the * in the cast, I would also like to see that diagnostic. I want to see how you went from "cannot dereference a double" to "cannot dereference because your target already is a double". -- Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-22 22:19 -0800 |
| Message-ID | <0c23e560-eae8-49e1-9f39-819c9162e204@googlegroups.com> |
| In reply to | #102351 |
On Sunday, January 22, 2017 at 10:08:21 PM UTC+3, Barry Schwarz wrote: > On Sun, 22 Jan 2017 08:16:07 -0800 (PST), Alla _ > <modelling.data@gmail.com> wrote: > > >On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote: > >> On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _ > > <snip> > > >> Here is the line of code I suggested > >> *(double*)((char*)dat_years + offset) = strtod(...); > >> > >> You chose to leave out a significant piece, apparently thinking it > >> didn't matter. > >Now it's my time to grumble )))) I didn't leave out that "significant piece, > >apparently (I wish you didn't use this word - it did make things worse) > >thinking it didn't matter" = wrong. I have mentioned *why* > >it is not in my code. I usually don't highlight things, because it is > >a rather bad manner, but sometimes even I get tired of groundless > >accusations - my compiler didn't allow me to use double casting > >because all values already are of double type. > > Yes, you did say this and it still makes no sense. The compiler may > know you are attempting to store into the structure but it has no idea > of which member. Especially since this is in a different function > than the one that computed offset. > > The parenthetical expression has type char*. It is legal (but not > usually meaningful) to cast this value to double. However, once you > do that, you are not allowed to dereference the result of that > operation. That is a constraint violation that has nothing to do with > the types of the members in your structure. > > There is no cast to double in my suggestion. There is a cast to > double*. Since the operand of that cast is a pointer to an object > type, there is no syntax constraint on casting the value to a pointer > to a different object type. The result may be implementation > dependent (or even undefined) but that is a different issue. > > If your compiler actually complained about a cast to double* (as > opposed to double as you stated), we would very much like to see THAT > code and the resulting diagnostic. > > If the problem is that you left off the * in the cast, I would also > like to see that diagnostic. I want to see how you went from "cannot > dereference a double" to "cannot dereference because your target > already is a double". Please, see my respond I have posted yesterday about my mistake. As to showing that wrong code, where I used (double) instead of (double*), and the diagnostic, I can't promise to do that because I have not saved any of those. Though I can scroll the Terminal back searching for it. Would you like me to do that? But you and James have already identified what it was and why I got an error message from a compiler and even what type of error it was.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-22 22:41 -0800 |
| Message-ID | <45f31c8d-4b4f-4833-9f1b-4dbb591e874a@googlegroups.com> |
| In reply to | #102351 |
On Sunday, January 22, 2017 at 10:08:21 PM UTC+3, Barry Schwarz wrote:
> On Sun, 22 Jan 2017 08:16:07 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
>
> >On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote:
> >> On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _
>
> <snip>
<snip>
What still is not clear to me is why the value of the offset of the second
member is 8, and not 4, if the first member has an int type, and on my
machine an int is 4 bytes. Is it due to the way all structure members
are being aligned? All other offsets are 8 because all other members
have type double. Here is a small test program that I wrote to see
the offsets of some structure, and I don't understand the result:
struct data {
int year;
char sales;
double cs_cogs;
char names[10];
};
Offset1 is zero, which is always the case; then I thought that
the offset2 will be 4 because the previous first member is an
int and it is indeed 4; but then the offset3 is 8, thought the
second member is a char - is it because the addresses
are all even? If so, why 4, and not 2?
Then offset4 is 26, while I have expected the difference
between offset3 and offset4 to be 8.
Here is the output:
Struct members' offsets
0 ; 4 ; 8 ; 26
Here is the program:
#include <stdio.h>
#include <stddef.h>
struct data {
int year;
char sales;
double cs_cogs;
char names[10];
};
int main(void)
{
struct data test;
int offset1 = offsetof(struct data, year);
int offset2 = offsetof(struct data, sales);
int offset3 = offsetof(struct data, cs_cogs);
int offset4 = offsetof(struct data, names[10]);
fprintf(stderr, "Struct members offsets\n");
fprintf(stderr, "%i ; %i ; %i ; %i \n", offset1, offset2, offset3, offset4);
return 0;
}
[toc] | [prev] | [next] | [standalone]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-01-23 02:17 -0600 |
| Message-ID | <uleb8c5p4a05feh9325q0a3uu6or6h3d1r@4ax.com> |
| In reply to | #102360 |
On Sun, 22 Jan 2017 22:41:16 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:
>On Sunday, January 22, 2017 at 10:08:21 PM UTC+3, Barry Schwarz wrote:
>> On Sun, 22 Jan 2017 08:16:07 -0800 (PST), Alla _
>> <modelling.data@gmail.com> wrote:
>>
>> >On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote:
>> >> On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _
>>
>> <snip>
><snip>
>What still is not clear to me is why the value of the offset of the second
>member is 8, and not 4, if the first member has an int type, and on my
>machine an int is 4 bytes. Is it due to the way all structure members
>are being aligned? All other offsets are 8 because all other members
>have type double. Here is a small test program that I wrote to see
>the offsets of some structure, and I don't understand the result:
>struct data {
> int year;
> char sales;
> double cs_cogs;
> char names[10];
>};
>Offset1 is zero, which is always the case; then I thought that
>the offset2 will be 4 because the previous first member is an
>int and it is indeed 4; but then the offset3 is 8, thought the
>second member is a char - is it because the addresses
>are all even? If so, why 4, and not 2?
>Then offset4 is 26, while I have expected the difference
>between offset3 and offset4 to be 8.
>
>Here is the output:
>Struct members' offsets
>0 ; 4 ; 8 ; 26
>
>Here is the program:
>#include <stdio.h>
>#include <stddef.h>
>
>struct data {
> int year;
> char sales;
> double cs_cogs;
> char names[10];
>};
>int main(void)
>{
> struct data test;
> int offset1 = offsetof(struct data, year);
> int offset2 = offsetof(struct data, sales);
> int offset3 = offsetof(struct data, cs_cogs);
> int offset4 = offsetof(struct data, names[10]);
> fprintf(stderr, "Struct members offsets\n");
> fprintf(stderr, "%i ; %i ; %i ; %i \n", offset1, offset2, offset3, offset4);
>
> return 0;
>}
cs_cogs is a double, and probably eight bytes in size, and its natural
alignment is probably eight bytes (both of those are platform
dependent, but 8 and 8 are by far the most common). So it will
normally be aligned on the next available 8 byte boundary after sales,
IOW at 8.
The next field (names) would start at 16, so if you did
"offsetof(struct data, names)", you should indeed get 16. But you did
"...names[10]...", which is asking for the offset of the 11th element
in the array "names". That 11th element is 10 bytes past the start of
the, hence the 26.
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2017-01-23 02:16 -0800 |
| Message-ID | <2pjb8chce4cuaihe7168u1ppqp1i6a4vgm@4ax.com> |
| In reply to | #102360 |
On Sun, 22 Jan 2017 22:41:16 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:
>What still is not clear to me is why the value of the offset of the second
>member is 8, and not 4, if the first member has an int type, and on my
>machine an int is 4 bytes. Is it due to the way all structure members
>are being aligned? All other offsets are 8 because all other members
>have type double. Here is a small test program that I wrote to see
>the offsets of some structure, and I don't understand the result:
>struct data {
> int year;
> char sales;
> double cs_cogs;
> char names[10];
>};
>Offset1 is zero, which is always the case; then I thought that
>the offset2 will be 4 because the previous first member is an
>int and it is indeed 4; but then the offset3 is 8, thought the
>second member is a char - is it because the addresses
>are all even? If so, why 4, and not 2?
>Then offset4 is 26, while I have expected the difference
>between offset3 and offset4 to be 8.
>
>Here is the output:
>Struct members' offsets
>0 ; 4 ; 8 ; 26
>
>Here is the program:
>#include <stdio.h>
>#include <stddef.h>
>
>struct data {
> int year;
> char sales;
> double cs_cogs;
> char names[10];
>};
As your output clearly shows, your structure has the following form:
bytes 0-3 contain years
byte 4 contains sales
bytes 5-7 contain padding to effect the needed alignment for cs_cogs
bytes 8-15 contain cs_cogs
byte 16 contains names[0]
byte 17 contains names[1]
...
byte 25 contains names[9]
bytes 26-31 contain padding to insure that sizeof(structure) is a
multiple of 8.
The value of each padding byte is indeterminate.
It is possible (though not at all likely) that there could be
additional padding starting at byte 32. If there is , that padding
must also be a multiple of 8 bytes since sizeof(structure) must still
be a multiple of 8. Additionally, structure has an alignment
requirement: it must start on an address that is a multiple of 8.
>int main(void)
>{
> struct data test;
> int offset1 = offsetof(struct data, year);
> int offset2 = offsetof(struct data, sales);
> int offset3 = offsetof(struct data, cs_cogs);
> int offset4 = offsetof(struct data, names[10]);
Semantically, this is an invalid use of the macro. The second
argument of the macro must be a member-designator. "names" is the
name of a member. names[0] is the first element of the array
designated by that member name so one could say it inherits "member
status". But names[10] is not an element of the array and therefore
cannot be a member-designator. If names actually occupied all the
bytes at the end of the structure, the offset calculated would be
beyond the end of the structure.
> fprintf(stderr, "Struct members offsets\n");
> fprintf(stderr, "%i ; %i ; %i ; %i \n", offset1, offset2, offset3, offset4);
>
> return 0;
>}
I'm almost sorry I suggested offsetof. It has caused you to become
sidetracked about issues unrelated to the project you are working on.
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-23 03:59 -0800 |
| Message-ID | <685ebfea-4531-4e59-a3d4-0db056521f92@googlegroups.com> |
| In reply to | #102362 |
On Monday, January 23, 2017 at 1:16:30 PM UTC+3, Barry Schwarz wrote:
> On Sun, 22 Jan 2017 22:41:16 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
>
> >What still is not clear to me is why the value of the offset of the second
> >member is 8, and not 4, if the first member has an int type, and on my
> >machine an int is 4 bytes. Is it due to the way all structure members
> >are being aligned? All other offsets are 8 because all other members
> >have type double. Here is a small test program that I wrote to see
> >the offsets of some structure, and I don't understand the result:
> >struct data {
> > int year;
> > char sales;
> > double cs_cogs;
> > char names[10];
> >};
> >Offset1 is zero, which is always the case; then I thought that
> >the offset2 will be 4 because the previous first member is an
> >int and it is indeed 4; but then the offset3 is 8, thought the
> >second member is a char - is it because the addresses
> >are all even? If so, why 4, and not 2?
> >Then offset4 is 26, while I have expected the difference
> >between offset3 and offset4 to be 8.
> >
> >Here is the output:
> >Struct members' offsets
> >0 ; 4 ; 8 ; 26
> >
> >Here is the program:
> >#include <stdio.h>
> >#include <stddef.h>
> >
> >struct data {
> > int year;
> > char sales;
> > double cs_cogs;
> > char names[10];
> >};
>
> As your output clearly shows, your structure has the following form:
> bytes 0-3 contain years
> byte 4 contains sales
> bytes 5-7 contain padding to effect the needed alignment for cs_cogs
> bytes 8-15 contain cs_cogs
> byte 16 contains names[0]
> byte 17 contains names[1]
> ...
> byte 25 contains names[9]
> bytes 26-31 contain padding to insure that sizeof(structure) is a
> multiple of 8.
>
> The value of each padding byte is indeterminate.
>
> It is possible (though not at all likely) that there could be
> additional padding starting at byte 32. If there is , that padding
> must also be a multiple of 8 bytes since sizeof(structure) must still
> be a multiple of 8. Additionally, structure has an alignment
> requirement: it must start on an address that is a multiple of 8.
>
> >int main(void)
> >{
> > struct data test;
> > int offset1 = offsetof(struct data, year);
> > int offset2 = offsetof(struct data, sales);
> > int offset3 = offsetof(struct data, cs_cogs);
> > int offset4 = offsetof(struct data, names[10]);
>
> Semantically, this is an invalid use of the macro. The second
> argument of the macro must be a member-designator. "names" is the
> name of a member. names[0] is the first element of the array
> designated by that member name so one could say it inherits "member
> status". But names[10] is not an element of the array and therefore
> cannot be a member-designator. If names actually occupied all the
> bytes at the end of the structure, the offset calculated would be
> beyond the end of the structure.
Thank you very much for this explanation; the issue is very clear
to me now.
>
> > fprintf(stderr, "Struct members offsets\n");
> > fprintf(stderr, "%i ; %i ; %i ; %i \n", offset1, offset2, offset3, offset4);
> >
> > return 0;
> >}
>
> I'm almost sorry I suggested offsetof. It has caused you to become
> sidetracked about issues unrelated to the project you are working on.
Oh, no! Please, don't be. I was just about to write a separate message
saying HUGE thanks to you for suggesting the offsetof because it did
solve so much trouble I wasn't able to solve for a while. And now I have
extended the usage of this macro, so I have only one function that
determines the "place" of members in two structs: data and assumptions,
and this function returns a tiny structure with two elements in it -
two offsets. Now I can easily compute all assumptions, I don't need
to invent horrific code, etc. Such a relief! So I am very thankful for your
help.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-01-23 08:44 -0800 |
| Message-ID | <lny3y1enez.fsf@kst-u.example.com> |
| In reply to | #102360 |
Alla _ <modelling.data@gmail.com> writes:
> On Sunday, January 22, 2017 at 10:08:21 PM UTC+3, Barry Schwarz wrote:
>> On Sun, 22 Jan 2017 08:16:07 -0800 (PST), Alla _
>> <modelling.data@gmail.com> wrote:
>>
>> >On Sunday, January 22, 2017 at 6:47:47 PM UTC+3, Barry Schwarz wrote:
>> >> On Sun, 22 Jan 2017 03:24:39 -0800 (PST), Alla _
>>
>> <snip>
> <snip>
> What still is not clear to me is why the value of the offset of the second
> member is 8, and not 4, if the first member has an int type, and on my
> machine an int is 4 bytes. Is it due to the way all structure members
> are being aligned? All other offsets are 8 because all other members
> have type double. Here is a small test program that I wrote to see
> the offsets of some structure, and I don't understand the result:
[snip]
This is probably irrelevant to what you're working on, but it's
covered in the comp.lang.c FAQ, <http://www.c-faq.com/>, questions
2.12 and following.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web