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


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

Preprocessor expressions

Started byBartC <bc@freeuk.com>
First post2017-01-22 13:24 +0000
Last post2017-01-30 05:30 -0800
Articles 15 on this page of 35 — 10 participants

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


Contents

  Preprocessor expressions BartC <bc@freeuk.com> - 2017-01-22 13:24 +0000
    Re: Preprocessor expressions jameskuyper@verizon.net - 2017-01-22 07:52 -0800
      Re: Preprocessor expressions Ralf Damaschke <rwspam@gmx.de> - 2017-01-22 17:15 +0000
        Re: Preprocessor expressions "James R. Kuyper" <jameskuyper@verizon.net> - 2017-01-22 13:32 -0500
      Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-01-22 17:38 +0000
        Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-01 03:12 -0800
          Re: Preprocessor expressions Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-01 11:44 +0000
          Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-01 11:56 +0000
          Re: Preprocessor expressions jameskuyper@verizon.net - 2017-02-01 08:35 -0800
            Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-02 09:23 -0800
              Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-02 18:14 +0000
                Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-02 10:35 -0800
                Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-02 17:09 -0800
                  Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-05 10:09 -0800
                  Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-05 10:38 -0800
                    Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-05 11:03 -0800
                      Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-06 15:17 +0000
                        Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-07 05:36 -0800
                          Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-07 21:01 +0000
                            Re: Preprocessor expressions supercat@casperkitty.com - 2017-02-07 13:16 -0800
                              Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-07 22:09 +0000
                                Re: Preprocessor expressions supercat@casperkitty.com - 2017-02-07 14:33 -0800
                                Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-07 14:52 -0800
                                  Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-08 00:13 +0000
                                    Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-07 16:39 -0800
                                    Re: Preprocessor expressions jameskuyper@verizon.net - 2017-02-07 16:47 -0800
                                Re: Preprocessor expressions David Brown <david.brown@hesbynett.no> - 2017-02-08 10:03 +0100
                                  Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-08 09:19 -0800
                            Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-08 12:35 -0800
                              Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-09 05:25 -0800
                                Re: Preprocessor expressions supercat@casperkitty.com - 2017-02-09 07:37 -0800
                                Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-09 15:52 +0000
    Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-01-22 19:34 +0000
      Re: Preprocessor expressions jameskuyper@verizon.net - 2017-01-22 13:01 -0800
    Re: Preprocessor expressions Tim Rentsch <txr@alumni.caltech.edu> - 2017-01-30 05:30 -0800

Page 2 of 2 — ← Prev page 1 [2]


#103421

FromBartC <bc@freeuk.com>
Date2017-02-07 22:09 +0000
Message-ID<o7dgfs$ksp$1@dont-email.me>
In reply to#103420
On 07/02/2017 21:16, supercat@casperkitty.com wrote:
> On Tuesday, February 7, 2017 at 3:01:36 PM UTC-6, Bart wrote:
>> My experience at the moment (translating from a non-C language to C, in
>> a recent working project) is that things such as pointer sizes, and
>> struct-member offsets, will be fixed. That means that generated C
>> requires things like pack(1), and to be compiled for a particular
>> pointer size.
>
> I would think it should be fairly straightforward to keep track of the
> required alignment for each type, and insert padding bytes in structure
> definitions as needed to maintain alignment.  While the Standard allows
> implementations to use arbitrary padding rules, the vast majority use
> a simple rule which says that every object will be preceded by whatever
> amount of padding would be needed to reach the next multiple of its
> alignment, and every structure or union will have the same alignment
> requirement as its coarsest member.  If your code knows the required
> alignment for each primitive, it should be able to add byte fields with
> dummy names so as to ensure that a compiler would never need to add any
> padding of its own unless it uses very weird structure layout rules.
>

I had once a project which had a struct with this layout:

   struct {
       int a;                // 32 bits
       double b;             // 64 bits
       int c;                // 32 bits
}

(The real thing was a lot more complex with anonymous unions everywhere. 
But it had carefully crafted to occupy 16 bytes in total.)

On x86-32, the compiler was quite happy to put member 'b' at offset 4.

But when I compiled it for 32-bit ARM, the same compiler, gcc, had to 
put 'b' at offset 8, which made the struct an odd size like 20 bytes.

This is why I think you can't always predict what a compiler will do.

(In the above example, I had to rearrange things so that 64-bit values 
were at 64-bit offsets, which was probably better, but there was nothing 
wrong with the original alignment that I could see. It didn't make the 
x86 version any faster.)

Anyway, when you're writing a compiler, then you have to be the one who 
makes the decisions. I might want a char[10] at an 8-byte alignment, and 
enforce it with explicit padding, but a C compiler might use 1-byte. Or 
the compiler can target C and D languages, and they do things differently.

You don't want to have to fight another compiler. And I bet C compilers 
aren't so considerate; do you think a C compiler can manage not to 
evaluate sizeof(void*), or the actual offsets of members in a struct, 
because someone wants to use a back-end that targets language X that has 
its own rules?

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#103422

Fromsupercat@casperkitty.com
Date2017-02-07 14:33 -0800
Message-ID<10429e90-d4cc-46ec-9967-0d1747ab5778@googlegroups.com>
In reply to#103421
On Tuesday, February 7, 2017 at 4:09:49 PM UTC-6, Bart wrote:
> On 07/02/2017 21:16, supercat wrote:
> I had once a project which had a struct with this layout:
> 
>    struct {
>        int a;                // 32 bits
>        double b;             // 64 bits
>        int c;                // 32 bits
> }
> 
> (The real thing was a lot more complex with anonymous unions everywhere. 
> But it had carefully crafted to occupy 16 bytes in total.)
> 
> On x86-32, the compiler was quite happy to put member 'b' at offset 4.
> 
> But when I compiled it for 32-bit ARM, the same compiler, gcc, had to 
> put 'b' at offset 8, which made the struct an odd size like 20 bytes.
> 
> This is why I think you can't always predict what a compiler will do.

When run on a compiler were type "double" can be placed at arbitrary 4-byte
boundaries, it will have one predictable behavior.  When run on a compiler
which requires 8-byte alignment, it will have a different predictable
behavior.

If you want to have consistent behavior on all platforms and don't need to
match up with any existing structure layouts, simply assume that any
primitive will require alignment equal to its size.  In some cases, that
may result in your code generator including more padding than would be
needed, but will result in compilers generating the same code when the
alignment is needed as when it isn't.

> Anyway, when you're writing a compiler, then you have to be the one who 
> makes the decisions. I might want a char[10] at an 8-byte alignment, and 
> enforce it with explicit padding, but a C compiler might use 1-byte. Or 
> the compiler can target C and D languages, and they do things differently.

Include your own padding members in a structure so that every member would
naturally start on the proper alignment boundary without any extra padding
and most compilers will lay it out exactly that way.  It would be much
better if the C Standard had let programmers explicitly specify what
alignment they need, rather than requiring them to rely upon implementation-
defined layout rules, but I'm not holding my breath for such features that
would make it practical to write portable code.

[toc] | [prev] | [next] | [standalone]


#103423

FromKeith Thompson <kst-u@mib.org>
Date2017-02-07 14:52 -0800
Message-ID<ln37fp1umt.fsf@kst-u.example.com>
In reply to#103421
BartC <bc@freeuk.com> writes:
[...]
> I had once a project which had a struct with this layout:
>
>    struct {
>        int a;                // 32 bits
>        double b;             // 64 bits
>        int c;                // 32 bits
> }
>
> (The real thing was a lot more complex with anonymous unions everywhere. 
> But it had carefully crafted to occupy 16 bytes in total.)
>
> On x86-32, the compiler was quite happy to put member 'b' at offset 4.
>
> But when I compiled it for 32-bit ARM, the same compiler, gcc, had to 
> put 'b' at offset 8, which made the struct an odd size like 20 bytes.

A size of 20 bytes seems unlikely.  If the compiler imposes 8-byte
alignment on type double, then it should also impose 8-byte alignment on
the structure.  The structure was probably 24 bytes.

> This is why I think you can't always predict what a compiler will do.

99% of the time you don't have to.  Usually you don't need to *tell* the
compiler how things are allocated, you can just *ask* it, using sizeof,
offsetof, and possibly _Alignof (which is new in C11).

> (In the above example, I had to rearrange things so that 64-bit values 
> were at 64-bit offsets, which was probably better, but there was nothing 
> wrong with the original alignment that I could see. It didn't make the 
> x86 version any faster.)

I presume you have valid reasons for wanting a particular layout.
(No sarcasm there, I really do presume you have valid reasons.
I don't particularly need to know what they are.)

[...]

-- 
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]


#103424

FromBartC <bc@freeuk.com>
Date2017-02-08 00:13 +0000
Message-ID<o7dno5$ei8$1@dont-email.me>
In reply to#103423
On 07/02/2017 22:52, Keith Thompson wrote:
> BartC <bc@freeuk.com> writes:
> [...]
>> I had once a project which had a struct with this layout:
>>
>>    struct {
>>        int a;                // 32 bits
>>        double b;             // 64 bits
>>        int c;                // 32 bits
>> }
>>
>> (The real thing was a lot more complex with anonymous unions everywhere.
>> But it had carefully crafted to occupy 16 bytes in total.)
>>
>> On x86-32, the compiler was quite happy to put member 'b' at offset 4.
>>
>> But when I compiled it for 32-bit ARM, the same compiler, gcc, had to
>> put 'b' at offset 8, which made the struct an odd size like 20 bytes.
>
> A size of 20 bytes seems unlikely.  If the compiler imposes 8-byte
> alignment on type double, then it should also impose 8-byte alignment on
> the structure.  The structure was probably 24 bytes.

So a struct of a double and an int is always going to be 16 bytes and 
never 12? (I used a 12-byte version for a while; I guess either that 
wasn't C, or I used pack(1).)

>> This is why I think you can't always predict what a compiler will do.
>
> 99% of the time you don't have to.  Usually you don't need to *tell* the
> compiler how things are allocated,

The context here is representing a struct whose layout has already been 
decided so that the C version has to match it exactly. Or the struct 
represents some layout in a file header, or a data packet from a comms 
link or whatever.

C is supposed to be low-level so why not allow that amount of control?

  you can just *ask* it, using sizeof,
> offsetof, and possibly _Alignof (which is new in C11).

Sure; but at the point where the decision is made (in another language 
or working out some file header), the C compiler stage may be some way 
off (in time, distance or done by someone else).

>> (In the above example, I had to rearrange things so that 64-bit values
>> were at 64-bit offsets, which was probably better, but there was nothing
>> wrong with the original alignment that I could see. It didn't make the
>> x86 version any faster.)
>
> I presume you have valid reasons for wanting a particular layout.
> (No sarcasm there, I really do presume you have valid reasons.
> I don't particularly need to know what they are.)

Again, C is not a high-level language where these details can be and 
usually are irrelevant.

For my purposes they can be very relevant. I've used variations of such 
a 16-byte struct since the mid-80s. I usually need to pack a lot in and 
it needs to be very carefully crafted because performance depends on 
keeping it compact.

(The latest version here: http://pastebin.com/rHqBYEqj. 26 or so fields 
in only 16 bytes. And this new version has had to offload a lot of stuff 
too thanks to 64-bit pointers taking up half the space.

But notice no padding is actually needed; the manual layout has already 
taken care of that.)

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#103425

FromKeith Thompson <kst-u@mib.org>
Date2017-02-07 16:39 -0800
Message-ID<lny3xhzfb8.fsf@kst-u.example.com>
In reply to#103424
BartC <bc@freeuk.com> writes:
> On 07/02/2017 22:52, Keith Thompson wrote:
>> BartC <bc@freeuk.com> writes:
>> [...]
>>> I had once a project which had a struct with this layout:
>>>
>>>    struct {
>>>        int a;                // 32 bits
>>>        double b;             // 64 bits
>>>        int c;                // 32 bits
>>> }
>>>
>>> (The real thing was a lot more complex with anonymous unions everywhere.
>>> But it had carefully crafted to occupy 16 bytes in total.)
>>>
>>> On x86-32, the compiler was quite happy to put member 'b' at offset 4.
>>>
>>> But when I compiled it for 32-bit ARM, the same compiler, gcc, had to
>>> put 'b' at offset 8, which made the struct an odd size like 20 bytes.
>>
>> A size of 20 bytes seems unlikely.  If the compiler imposes 8-byte
>> alignment on type double, then it should also impose 8-byte alignment on
>> the structure.  The structure was probably 24 bytes.
>
> So a struct of a double and an int is always going to be 16 bytes and 
> never 12? (I used a 12-byte version for a while; I guess either that 
> wasn't C, or I used pack(1).)

The alignment of any structure type is always at least the alignment of
any of its members, and the size is always a whole multiple of the
alignment.  This is necessary for array indexing to work.  (Trailing
padding might not be necessary if arrays could have gaps between
elements, but C doesn't permit that.)

>>> This is why I think you can't always predict what a compiler will do.
>>
>> 99% of the time you don't have to.  Usually you don't need to *tell* the
>> compiler how things are allocated,
>
> The context here is representing a struct whose layout has already been 
> decided so that the C version has to match it exactly. Or the struct 
> represents some layout in a file header, or a data packet from a comms 
> link or whatever.

Yes, an externally imposed format is certainly a valid reason.

> C is supposed to be low-level so why not allow that amount of control?

I'm not going to debate what C *should* do.

[...]

>> I presume you have valid reasons for wanting a particular layout.
>> (No sarcasm there, I really do presume you have valid reasons.
>> I don't particularly need to know what they are.)
>
> Again, C is not a high-level language where these details can be and 
> usually are irrelevant.
>
> For my purposes they can be very relevant. I've used variations of such 
> a 16-byte struct since the mid-80s. I usually need to pack a lot in and 
> it needs to be very carefully crafted because performance depends on 
> keeping it compact.
>
> (The latest version here: http://pastebin.com/rHqBYEqj. 26 or so fields 
> in only 16 bytes. And this new version has had to offload a lot of stuff 
> too thanks to 64-bit pointers taking up half the space.
>
> But notice no padding is actually needed; the manual layout has already 
> taken care of that.)

Right, if you can order the fields so that the most strictly aligned
members are first, you can often avoid padding.  And many C
implementations have extensions that let you specify packing (often at
the expense of slower code).

Note that gcc's packing extensions, and likely those of other languages,
can be unsafe if you're not careful.  For example, if you have a
structure like
    struct { char c; int x; };
and you use an extension to force the int member to be misaligned, then
the compiler will generate correct code if you access obj.x, but if it
let's you take the address of a misaligned member, any code that
dereference the resulting pointer can blow up.

http://stackoverflow.com/q/8568432/827263
http://stackoverflow.com/a/8568441/827263

If you really need absolute control over layout (short of using a
different language), you can alway manipulate your data using arrays of
unsigned char with memcpy().  The result is going to be extremely
tedious.  I'm not recommending it, just pointing out that the
possibility is there.

I'll also mention that most externally imposed data layouts are likely
designed to be used from C code, and will therefore tend to avoid
alignment problems.  Of course that's not much help if you happen to be
dealing with a layout that wasn't designed that way.

-- 
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]


#103426

Fromjameskuyper@verizon.net
Date2017-02-07 16:47 -0800
Message-ID<7aed557d-1bf1-4dba-8752-1b362fcf7053@googlegroups.com>
In reply to#103424
On Tuesday, February 7, 2017 at 7:13:43 PM UTC-5, Bart wrote:
> On 07/02/2017 22:52, Keith Thompson wrote:
> > BartC <bc@freeuk.com> writes:
> > [...]
> >> I had once a project which had a struct with this layout:
> >>
> >>    struct {
> >>        int a;                // 32 bits
> >>        double b;             // 64 bits
> >>        int c;                // 32 bits
> >> }
> >>
> >> (The real thing was a lot more complex with anonymous unions everywhere.
> >> But it had carefully crafted to occupy 16 bytes in total.)
> >>
> >> On x86-32, the compiler was quite happy to put member 'b' at offset 4.
> >>
> >> But when I compiled it for 32-bit ARM, the same compiler, gcc, had to
> >> put 'b' at offset 8, which made the struct an odd size like 20 bytes.
> >
> > A size of 20 bytes seems unlikely.  If the compiler imposes 8-byte
> > alignment on type double, then it should also impose 8-byte alignment on
> > the structure.  The structure was probably 24 bytes.
> 
> So a struct of a double and an int is always going to be 16 bytes and 
> never 12?

That depends upon the value of _Alignof(double). A compiler that puts b at an offset of 8 is likely to be one that has _Alignof(double)==8.

> (I used a 12-byte version for a while; I guess either that 
> wasn't C, or I used pack(1).)

If _Alignof(double)<=4, then a size of 12 for a struct containing a 4-byte int and an 8-byte double is not only possible, but likely. Note, however, that on some implementations, all structs are given an alignment requirement equal to the strictest alignment imposed by that implementation for any scalar type. If that maximum requirement is greater than 4, then the size of such a struct will be greater than 12, even if the double member is held at an offset of 4, even though the struct doesn't contain any objects with an alignment requirement that strict.

...
> C is supposed to be low-level so why not allow that amount of control?

The designers of C decided to allow for implementations on platforms where hardware issues make it necessary (or at least highly desireable) for objects of type T had to be aligned in accordance with  what we now call _Alignof(T). You're probably familiar only with platforms where incorrectly aligned access is merely slow; there are others where it's essentially impossible, and can only be emulated.
The rules for how C arrays are handled imply that if a member of a struct has a given alignment requirement, then the struct as a whole must have an alignment requirement that is at least as strict as that member's requirement. Which means that the offset of such a member has to be a multiple of the member's alignment requirement.

If you want packing without regard for alignment requirements, use an arrays of unsigned char, and memcpy() into that array from correctly aligned storage, or memcpy() from that array to correctly aligned storage.

...
> But notice no padding is actually needed; the manual layout has already 
> taken care of that.)

The compiler thought that alignment on multiples of 4 bytes was insufficient. I would recommend finding out why, before automatically assuming that it was wrong.

[toc] | [prev] | [next] | [standalone]


#103433

FromDavid Brown <david.brown@hesbynett.no>
Date2017-02-08 10:03 +0100
Message-ID<o7emp7$ikl$1@dont-email.me>
In reply to#103421
On 07/02/17 23:09, BartC wrote:
> On 07/02/2017 21:16, supercat@casperkitty.com wrote:
>> On Tuesday, February 7, 2017 at 3:01:36 PM UTC-6, Bart wrote:
>>> My experience at the moment (translating from a non-C language to C, in
>>> a recent working project) is that things such as pointer sizes, and
>>> struct-member offsets, will be fixed. That means that generated C
>>> requires things like pack(1), and to be compiled for a particular
>>> pointer size.
>>
>> I would think it should be fairly straightforward to keep track of the
>> required alignment for each type, and insert padding bytes in structure
>> definitions as needed to maintain alignment.  While the Standard allows
>> implementations to use arbitrary padding rules, the vast majority use
>> a simple rule which says that every object will be preceded by whatever
>> amount of padding would be needed to reach the next multiple of its
>> alignment, and every structure or union will have the same alignment
>> requirement as its coarsest member.  If your code knows the required
>> alignment for each primitive, it should be able to add byte fields with
>> dummy names so as to ensure that a compiler would never need to add any
>> padding of its own unless it uses very weird structure layout rules.
>>
> 
> I had once a project which had a struct with this layout:
> 
>   struct {
>       int a;                // 32 bits
>       double b;             // 64 bits
>       int c;                // 32 bits
> }
> 
> (The real thing was a lot more complex with anonymous unions everywhere.
> But it had carefully crafted to occupy 16 bytes in total.)
> 
> On x86-32, the compiler was quite happy to put member 'b' at offset 4.
> 
> But when I compiled it for 32-bit ARM, the same compiler, gcc, had to
> put 'b' at offset 8, which made the struct an odd size like 20 bytes.

It will be 24 bytes, with padding at the end too.

> 
> This is why I think you can't always predict what a compiler will do.

Perhaps /you/ can't predict what the compiler will do - but people who
know their compilers can.  The alignment of types is implementation
dependent - it can vary between compilers (even on the same platform),
but will be consistent and predictable for any given implementation.

As Supercat says, the easiest method is to assume that alignment matches
size - then your structs will never be bigger than you expect.
Alignment of a type can never be bigger than the type's size (counting
any internal padding bits in the type as part of its size).

If you want to avoid structs being smaller than you expect, add padding
explicitly.

So with

   struct X {
       double b;             // 64 bits
       int a;                // 32 bits
       int c;                // 32 bits
 };

You will always get 16 byte structs with 8 byte alignment (assuming
CHAR_BIT == 8).  If you really want the order a, b, c and you want to be
sure of the layout on all systems (with the same size of int and
double), use:

   struct Y {
       int a;                // 32 bits
       int padding1;
       double b;             // 64 bits
       int c;                // 32 bits
       int padding2;
 }

If you are using gcc, then you can use "-Wpadded" to give you a warning
if the compiler has inserted struct padding itself.

It is also a good idea to check your structs - static_assert() is your
key tool here:

	static_assert(sizeof(struct X) == 16);
	static_assert(sizeof(struct Y) == 24);

offsetof can also come in handy when checking large struct layouts.


(This is something I have to do regularly, for structs that match
hardware register layouts, data communicated between devices, or data
stored in non-volatile memory.)

[toc] | [prev] | [next] | [standalone]


#103479

FromKeith Thompson <kst-u@mib.org>
Date2017-02-08 09:19 -0800
Message-ID<lntw84zjkj.fsf@kst-u.example.com>
In reply to#103433
David Brown <david.brown@hesbynett.no> writes:
[...]
> If you want to avoid structs being smaller than you expect, add padding
> explicitly.
>
> So with
>
>    struct X {
>        double b;             // 64 bits
>        int a;                // 32 bits
>        int c;                // 32 bits
>  };
>
> You will always get 16 byte structs with 8 byte alignment (assuming
> CHAR_BIT == 8).

*And* assuming that double is 64 bits and int is 32 bits.  Neither is
guaranteed.

If you're implementing something that generates C code, and if the
translator and/or the generated C code are intended to be reasonably
portable, it's probably a good idea for the generator to be aware of
some of the characteristics of the target system.  In some cases, some
of this parameterization has already been done by <stdint.h>.

-- 
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]


#103486

FromThiago Adams <thiago.adams@gmail.com>
Date2017-02-08 12:35 -0800
Message-ID<857402db-192f-4b61-b416-b473b4063619@googlegroups.com>
In reply to#103419
On Tuesday, February 7, 2017 at 7:01:36 PM UTC-2, Bart wrote:
[...]
> But later on, I'm likely to play around with some, although my ideas of 
> worthwhile extensions are going to be different from yours, gcc's, or 
> anyone else's.


I am starting to think that the most valuable addition to C would 
be templates. 


---------- Array.h

template <class T>
struct Array
{
     T **pItems=0;
     int Size=0;
     int Capacity=0;
};
    
 template<class T>
 int Push(Array<T>* array, T i)
 {
     return 1;
 }

---------- Main.c

#include "Array.h" 

int main(int argc, char **argv)
{
    Array<int> a = {};
    Push(&a, 1);
}

-x-

Generated code:

---------- Main.c

//Template declarations are removed from Array.h
#include "Array.h"

//BEGIN ADDED
typedef struct 
{
     int **pItems;
     int Size;
     int Capacity;
} ArrayInt;

#define ARRAYINT_INIT {0,0,0}

int PushArrayIntInt(ArrayInt* array, int i)
{
     return 1;
}
//END ADDED

int main(int argc, char **argv)
{
    ArrayInt a = ARRAYINT_INIT;
    PushArrayIntInt(&a, 1);
}

[toc] | [prev] | [next] | [standalone]


#103517

FromThiago Adams <thiago.adams@gmail.com>
Date2017-02-09 05:25 -0800
Message-ID<affe9e12-0221-499f-a07c-eb41d4a03c3c@googlegroups.com>
In reply to#103486
On Wednesday, February 8, 2017 at 6:35:16 PM UTC-2, Thiago Adams wrote:
[...]
> I am starting to think that the most valuable addition to C would 
> be templates. 

I want to rephrase this.

I am starting to think that the most valuable addition to an 
separated C extension language would be templates. 

Some interesting links about the origins of templates in C++:

http://www.softwarepreservation.org/projects/c_plus_plus/library

http://www.softwarepreservation.org/projects/c_plus_plus/library/cool/cool-parameterized-types.pdf

[toc] | [prev] | [next] | [standalone]


#103519

Fromsupercat@casperkitty.com
Date2017-02-09 07:37 -0800
Message-ID<6654717e-0ed8-440f-880c-63a02ce9c1d8@googlegroups.com>
In reply to#103517
On Thursday, February 9, 2017 at 7:25:12 AM UTC-6, Thiago Adams wrote:
> I am starting to think that the most valuable addition to an 
> separated C extension language would be templates. 

Which would you see as more useful: a template system whose design is fairly rigid, or a set of preprocessor-like features that were integrated into the main language rather than than stuck onto the front (allowing things like expression evaluation, which could in turn allow conditionally-recursive macros), and could be used to create templates but could also be used for other purposes as well?

[toc] | [prev] | [next] | [standalone]


#103523

FromBartC <bc@freeuk.com>
Date2017-02-09 15:52 +0000
Message-ID<o7i34a$sc2$1@dont-email.me>
In reply to#103517
On 09/02/2017 13:25, Thiago Adams wrote:
> On Wednesday, February 8, 2017 at 6:35:16 PM UTC-2, Thiago Adams wrote:
> [...]
>> I am starting to think that the most valuable addition to C would
>> be templates.
>
> I want to rephrase this.
>
> I am starting to think that the most valuable addition to an
> separated C extension language would be templates.

Most people would ask, why not just use C++?

I think templates are of those features that looks deceptively simple 
but rapidly gets complicated when you look at more details and more 
examples. Like C's macro-processor, in spades.

Things like multiple type arguments; nested templates; recursive 
templates; choosing which combination of types matches which template; 
and what exactly constitutes a distinct type?

You example of a stack of structs: would there need to be separate 
push/pop for each struct type, or would a more general purpose one that 
works for any struct of a certain length, or for any struct or other 
type that can be considered to be a block of types?

There is also the likelihood that, bit by bit as issues arise, you will 
need yet another feature from C++.

I can appreciate what templates can do, but can't see how to add them in 
a simple fashion. Not at this level of language. (A dynamic language can 
do most of what templates can add, but it will be slower.)

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#102354

FromBartC <bc@freeuk.com>
Date2017-01-22 19:34 +0000
Message-ID<o631dt$q3b$1@dont-email.me>
In reply to#102319
On 22/01/2017 13:24, BartC wrote:
> These are the ones that occur after #if and #elif.

I forgot to ask. Are preprocessor expressions evaluated as signed, 
unsigned, mixed, or doesn't it matter?

(Some operations such as multiply and right shift can give different 
results between signed and unsigned.)

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#102356

Fromjameskuyper@verizon.net
Date2017-01-22 13:01 -0800
Message-ID<d428bd49-8957-4e26-9bdb-0869832a960e@googlegroups.com>
In reply to#102354
On Sunday, January 22, 2017 at 2:35:03 PM UTC-5, Bart wrote:
> On 22/01/2017 13:24, BartC wrote:
> > These are the ones that occur after #if and #elif.
> 
> I forgot to ask. Are preprocessor expressions evaluated as signed, 
> unsigned, mixed, or doesn't it matter?

It very definitely matters. Whether or not an expression has a signed or unsigned type is determined the same way as in normal C expressions, but once that determination is made, all signed types are treated as if they had the same representation as intmax_t, and all unsigned types are treated as if they had the same representation as uintmax_t (6.10.1p4)

[toc] | [prev] | [next] | [standalone]


#102754

FromTim Rentsch <txr@alumni.caltech.edu>
Date2017-01-30 05:30 -0800
Message-ID<kfn1svkhdyu.fsf@x-alumni2.alumni.caltech.edu>
In reply to#102319
BartC <bc@freeuk.com> writes:

> These are the ones that occur after #if and #elif.
>
> The standard 6.10p1 says these are constant-expressions.  But the
> latter (A.2.1) can apparently include casts, ++, sizeof, ., ->, [] and
> and all the rest.
>
> 6.6 says little about constant expressions except that it rules out ++
> and -- (assignment and so on are ruled out by the grammar).
>
> Where are the restrictions for what are allowed in #if expressions?

Section 6.10.1 gives two constraints for these, and defines the
semantics.

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c


csiph-web