Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #102281 > unrolled thread

Optimizing the code: way to reduce if, else if-s within the loop?

Started byAlla _ <modelling.data@gmail.com>
First post2017-01-21 08:52 -0800
Last post2017-01-23 07:08 -0800
Articles 20 on this page of 55 — 11 participants

Back to article view | Back to comp.lang.c


Contents

  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 →


#102350

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-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]


#102352

FromBartC <bc@freeuk.com>
Date2017-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]


#102358

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-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]


#102363

FromAlla _ <modelling.data@gmail.com>
Date2017-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]


#102367

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-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]


#102368

FromAlla _ <modelling.data@gmail.com>
Date2017-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]


#102370

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-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]


#102312

FromAlla _ <modelling.data@gmail.com>
Date2017-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, &not_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]


#102317

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-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, &not_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]


#102328

FromBarry Schwarz <schwarzb@dqel.com>
Date2017-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, &not_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]


#102334

FromAlla _ <modelling.data@gmail.com>
Date2017-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, &not_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]


#102338

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-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, &not_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]


#102353

FromAlla _ <modelling.data@gmail.com>
Date2017-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, &not_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]


#102351

FromBarry Schwarz <schwarzb@dqel.com>
Date2017-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]


#102359

FromAlla _ <modelling.data@gmail.com>
Date2017-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]


#102360

FromAlla _ <modelling.data@gmail.com>
Date2017-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]


#102361

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-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]


#102362

FromBarry Schwarz <schwarzb@dqel.com>
Date2017-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]


#102369

FromAlla _ <modelling.data@gmail.com>
Date2017-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]


#102376

FromKeith Thompson <kst-u@mib.org>
Date2017-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