Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #102319 > unrolled thread
| Started by | BartC <bc@freeuk.com> |
|---|---|
| First post | 2017-01-22 13:24 +0000 |
| Last post | 2017-01-30 05:30 -0800 |
| Articles | 15 on this page of 35 — 10 participants |
Back to article view | Back to comp.lang.c
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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-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]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-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