Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #93474 > unrolled thread
| Started by | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| First post | 2016-09-14 12:01 -0700 |
| Last post | 2016-09-15 11:23 -0700 |
| Articles | 20 on this page of 99 — 14 participants |
Back to article view | Back to comp.lang.c
Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 12:01 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 13:15 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 13:27 -0700
Re: Sugestions for runtime polymorphism Richard Heathfield <rjh@cpax.org.uk> - 2016-09-14 21:50 +0100
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 14:20 -0700
Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-14 17:32 -0400
Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-14 16:30 -0700
Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-14 17:54 -0400
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 17:34 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 17:58 -0700
Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-14 19:50 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 05:03 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-15 10:43 +0100
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 05:29 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-15 19:49 +0100
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 11:58 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-15 20:29 +0100
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 14:00 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-16 07:27 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-16 16:34 +0100
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-16 09:36 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-20 12:59 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-20 14:08 -0700
Re: Sugestions for runtime polymorphism Ian Collins <ian-news@hotmail.com> - 2016-09-21 15:53 +1200
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-21 07:38 -0700
Re: Sugestions for runtime polymorphism Ian Collins <ian-news@hotmail.com> - 2016-09-23 09:12 +1200
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-21 05:26 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-21 05:35 -0700
Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-21 06:01 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-22 01:44 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-22 13:16 +0100
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-22 08:02 -0700
Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-22 11:44 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-22 09:52 -0700
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-23 09:49 +0200
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-23 07:55 -0700
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-24 16:29 +0200
Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-24 15:56 +0100
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-24 17:50 +0200
Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-24 13:45 -0400
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-24 11:26 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 10:38 -0700
Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-24 21:03 +0100
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 12:43 +0200
Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-25 11:48 -0400
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 18:39 +0200
Re: Sugestions for runtime polymorphism "James R. Kuyper" <jameskuyper@verizon.net> - 2016-09-25 13:14 -0400
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-25 13:47 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 10:39 -0700
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 23:25 +0200
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-25 13:10 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-25 12:55 -0700
Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-25 20:38 +0100
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 23:20 +0200
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 07:15 -0700
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-28 21:29 +0200
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-24 10:52 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-24 10:33 -0700
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-25 12:46 +0200
Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-24 13:58 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-28 04:46 -0700
Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-24 00:07 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 08:52 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-23 09:56 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 12:00 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-22 08:45 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-22 09:36 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-23 12:06 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-23 15:29 -0700
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-29 07:56 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-30 10:54 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-30 11:18 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-30 19:26 +0100
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-30 12:41 -0700
Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-30 21:07 +0100
Re: Sugestions for runtime polymorphism Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-30 23:30 -0700
Re: Sugestions for runtime polymorphism Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-01 11:35 +0100
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-10-01 14:44 -0700
Re: Sugestions for runtime polymorphism Richard Heathfield <rjh@cpax.org.uk> - 2016-09-14 22:56 +0100
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-15 13:19 +0200
Re: Sugestions for runtime polymorphism James Kuyper <jameskuyper@verizon.net> - 2016-09-15 08:07 -0400
Re: Sugestions for runtime polymorphism David Brown <david.brown@hesbynett.no> - 2016-09-15 14:24 +0200
Re: Sugestions for runtime polymorphism Richard Heathfield <rjh@cpax.org.uk> - 2016-09-15 15:34 +0100
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-15 05:10 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-15 09:12 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-14 23:32 +0100
Re: Sugestions for runtime polymorphism "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-09-14 17:35 -0700
Re: Sugestions for runtime polymorphism Ian Collins <ian-news@hotmail.com> - 2016-09-15 16:24 +1200
Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-15 10:31 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-14 22:53 +0100
Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-14 16:56 -0700
Re: Sugestions for runtime polymorphism supercat@casperkitty.com - 2016-09-14 15:58 -0700
Re: Sugestions for runtime polymorphism Keith Thompson <kst-u@mib.org> - 2016-09-14 18:49 -0700
Re: Sugestions for runtime polymorphism luser droog <luser.droog@gmail.com> - 2016-09-14 14:17 -0700
Re: Sugestions for runtime polymorphism Thiago Adams <thiago.adams@gmail.com> - 2016-09-14 14:25 -0700
Re: Sugestions for runtime polymorphism luser droog <luser.droog@gmail.com> - 2016-09-14 14:40 -0700
Re: Sugestions for runtime polymorphism luser droog <luser.droog@gmail.com> - 2016-09-14 14:57 -0700
Re: Sugestions for runtime polymorphism BartC <bc@freeuk.com> - 2016-09-14 23:10 +0100
Re: Sugestions for runtime polymorphism Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-15 11:23 -0700
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-28 04:46 -0700 |
| Message-ID | <kfn4m50ckmk.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93994 |
Keith Thompson <kst-u@mib.org> writes:
> supercat@casperkitty.com writes:
>> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
>>> On 22/09/16 18:52, supercat wrote:
>>> Your first claim was that gcc (6.2) incorrectly handles code in a way
>>> that goes against the unambiguous rules of the standards. This is a
>>> serious allegation, and should be backed up with concrete examples and
>>> bug reports. The gcc team take all "incorrect code generation" bugs
>>> extremely seriously. And while /you/ might not use gcc, millions of
>>> others do use it. Someone here (such as me) will happily file a bug
>>> report if you have a specific bug.
>>>
>>> But now you have modified back to your usual "gcc optimises too well -
>>> it follows the requirements of the real C standards, rather than my
>>> imaginary specifications of thirty years ago".
>>>
>>> So which is it? Can you give us a concrete example of buggy code, that
>>> we can paste into <http://gcc.godbolt.org/#> and compare results with
>>> different gcc versions and different compilers? You can't just refer to
>>> "I've posted about it before" - you have posted hundreds or thousands of
>>> snippets in this group.
>>
>> #include <stdint.h>
>> #include <string.h>
>> #include <stdlib.h>
>> #include <stdio.h>
>>
>> typedef long long T1;
>> typedef int64_t T2;
>> #define T1FMT "%lld"
>> #define T1VALUE 1
>> #define T2VALUE 2
>>
>> T1 blah3(void *p1, void *p2)
>> {
>> T1 *t1p, *t1p2;
>> T2 *t2p;
>> T1 temp;
>>
>> t1p = p1;
>> t2p = p2;
>> *t1p = T1VALUE; // Write as T1
>> *t2p = T2VALUE; // Write as T2
>> temp = *t2p; // Read as T2
>> t1p2 = (T1*)t2p; // Visible T2 to T1 pointer conversion
>> *t1p2 = temp; // Write as T1
>> return *t1p; // Read as T1
>> }
>>
>> T1 test3(void)
>> {
>> void *p = malloc(sizeof (T1) + sizeof (T2));
>> T1 result = blah3(p,p);
>> free(p);
>> return result;
>> }
>> int main(void)
>> {
>> T1 result = test3();
>> printf("The result is " T1FMT, result);
>> return 0;
>> }
>
> [...]
>
>> So there's a sample of buggy code. Similar thing can happen if there are
>> two structure types that have the same representation.
>
> I found that the typedefs and macros made the code difficult to read;
> YMMV.
This reaction surprised me. I too found the code a bit hard to
read, but not especially because of using typedefs and macros.
To me the rewrite using concrete types (directly below) isn't any
easier, and possibly is harder (let me emphasize, that is just a
personal reaction).
> Here's my version, which I believe is equivalent -- assuming
> that long and long long have the same size and representation,
> and that int64_t is a typedef for long. (I also added a newline
> to the output.)
>
> On my x86_64 system, using gcc 6.2.0, I get "The result is 2"
> with -O0 and -O1, and "The result is 1" with -O2 and -O3.
>
> #include <string.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <assert.h>
>
> long long func1(void *p1, void *p2) {
> long long *llp1 = p1;
> long *lp = p2;
> *llp1 = 1; // Write as long long
> *lp = 2; // Write as long
> long long temp = *lp; // Read as long
> long long *llp2 = (long long*)lp; // Visible long to long long
> pointer conversion
> *llp2 = temp; // Write as long long
> return *llp1; // Read as long long
> }
>
> long long func2(void) {
> void *p = malloc(sizeof (long long) + sizeof (long));
> long long result = func1(p,p);
> free(p);
> return result;
> }
>
> int main(void) {
> assert(sizeof (long) == sizeof (long long));
> printf("The result is %lld\n", func2());
> }
I might write code for this test case as follows. The code below
exhibits the same symptom (ie, different results at different
optimization settings) in two different versions of gcc, one of
which is 32-bit, and the other 64-bit. (Note: in all cases the
output was either 1 or 2.)
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
/*****************************************************************
* Define type names A and B to be distinct integer types (both
* signed) that cover the same range of values, and hence
* presumably have the same representation.
*****************************************************************/
#if LLONG_MIN == LONG_MIN
typedef long long A;
typedef long B;
#elif LONG_MIN == INT_MIN
typedef long A;
typedef int B;
#endif
A
func1( A *const pa, B *const pb ){
*pa = 1;
*pb = 2;
*(A*)pb = 2;
return *pa;
}
int
func2( void ){
assert( sizeof (A) == sizeof (B) );
void *p = malloc( sizeof (A) );
int result = func1( p, p );
free( p );
return result;
}
int
main( void ){
printf( "The result is %d\n", func2() );
}
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-09-24 00:07 -0700 |
| Message-ID | <0e81fb4c-3abb-472c-ade8-960ff023e11d@googlegroups.com> |
| In reply to | #93930 |
On Friday, September 23, 2016 at 8:49:43 AM UTC+1, David Brown wrote: > On 22/09/16 18:52, supercat@casperkitty.com wrote: > > Your first claim was that gcc (6.2) incorrectly handles code in a way > that goes against the unambiguous rules of the standards. This is a > serious allegation, and should be backed up with concrete examples and > bug reports. > No, it's a bug report. If you can contrive some extremely obscure and unlikely piece of C, that causes gcc to violate some aspect of the standard that very few people are aware of and that doesn't impact on everyday, practical programs, it is clear bug. But not a serious allegation.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-23 08:52 -0700 |
| Message-ID | <kfnintmehq6.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93891 |
BartC <bc@freeuk.com> writes:
> On 22/09/2016 09:44, Tim Rentsch wrote:
>> Thiago Adams <thiago.adams@gmail.com> writes:
>>
>>> [accomplishing type changing using a 'union' pattern]
>>
>> /* These functions provide type conversion */
>> static inline Foo as_Foo( Object it ){ return (Foo)it; }
>> static inline Bas as_Bas( Object it ){ return (Bas)it; }
>>
>> Taking an approach along these lines gets rid of any need to use
>> unions, and the behavior it relies on is blessed by the Standard.
>
> So you've got rid of unions by using casts everywhere instead
> [continues next]
No, there are casts only in the as_...() conversion functions, of
which there is just one per subtype. Presumably the conversion
functions will be used fairly widely, but actual casts are
localized to just the bodies of the conversion functions. For
how that difference matters, see next.
> (presumably as being the lesser 'evil').
>
> But unions result in less intrusion within the code.
That depends on what metric is used to measure "intrusion." At a
local level there isn't much difference syntactically between the
two approaches.
The reasons for avoiding unions are more semantic than syntactic.
Using unions to do type punning is easy to get wrong and often
easy to miss in terms of where it is used: it relies on
different types having related (or identical) representations,
which is not always the case, and it requires union members to be
accessed using certain patterns and not other patterns that look
like they should be equivalent. Furthermore, it is not uncommon
for compilers to get these rules wrong on occasion. Also, in C++
(as I was reminded recently), any use of unions to accomplish
type punning is always undefined behavior. Compared to unions,
type conversion is more obvious in its use and more reliable
in its effect.
A pitfall with adopting a type conversion approach is using casts
in open code. Casting is a sledgehammer - a cast will cheerfully
smash whatever value is casted, including values whose type may
not be appropriate. Using type conversion functions instead has
several benefits. One, it is often easier to find where they are
used. Two, the conversion functions are type safe - they work
only on values of an appropriate type, rather than any pointer
type. Three, any use of a cast should raise a red flag, so
limiting the number of casts used makes code easier to understand
and review. Four, in this particular case, where the type
conversion is tied to a tag field in the object being pointed to,
wrapping the conversion in a function allows the conversion
functions to be changed to detect bad uses. So for example:
static inline Foo
as_Foo( Object it ){
assert( it->type == OT_Foo );
return (Foo)it;
}
With this change the conversion functions can be used without any
worry that they are being used wrongly, which is very helpful in
a program of any significant size.
> (Also, depending on the actual arrangement, they can make it
> easier to share common fields other than just .type.)
Not if the uses must be done safely. Using unions to support
common prefixing is a big PITA if what the Standard requires for
such uses must be met. (And if being compiled as C++ is a
consideration, then it can't be done at all.)
By contrast, it isn't hard to arrange nested struct definions
so sub-sub-types or sub-sub-sub-types or sub-sub-sub-sub-types
are not too bad. And if the nesting is greater than three or
four then it is almost certainly the case that C is just not
the right language for the application in question.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-23 09:56 -0700 |
| Message-ID | <a2334ec9-a405-4a2a-91e8-1dc7f105698e@googlegroups.com> |
| In reply to | #93952 |
On Friday, September 23, 2016 at 10:52:42 AM UTC-5, Tim Rentsch
> Not if the uses must be done safely. Using unions to support
> common prefixing is a big PITA if what the Standard requires for
> such uses must be met. (And if being compiled as C++ is a
> consideration, then it can't be done at all.)
What would be the purpose of specifying that the *complete* union
declaration be visible if not to make clear that an incomplete one
is not acceptable?
The primary value of the CIS guarantees lay in the fact that the only way
compilers could meet them was by allowing pointer to a struct to be used
to access the CIS of any other. The ability to use a pointer to one struct
to access members of the CIS of another struct was clearly part of C74;
later versions of C added the requirement to use a typecast when converting
pointer types, but at no point was the use of a suitably-cast struct pointer
to read members of another struct's CIS ever explicitly deprecated.
If one interprets the existence of a complete visible "union" declaration
containing two structure types is regarded as giving the compiler adequate
notice that a pointer of one structure type may be used to access members
of the CIS of anther, such an interpretation will uphold the semantics
which have been well established since 1974. Without that ability, there
is no clean way to write code that can accept pointers to a variety of
structure types that have different alignment requirements and access
members of the CIS thereof, in cases where the length of the CIS is not
a multiple of the coarsest alignment requirement among its members (e.g.
where the CIS would contain a "void*" and a "uint16_t").
Given that such semantics were clearly available in C74 and are not
available under gcc's interpretation, that would imply that they were
removed at some time in-between? When? Is there any reason that there
was no formal deprecation prior to removal?
Or do those who claim that gcc's interpretation is correct not represent
the view of everyone who approved the language in the C99 Standard?
> By contrast, it isn't hard to arrange nested struct definions
> so sub-sub-types or sub-sub-sub-types or sub-sub-sub-sub-types
> are not too bad. And if the nesting is greater than three or
> four then it is almost certainly the case that C is just not
> the right language for the application in question.
How would you efficiently implement a function that can accept things of
arbitrary types that start with a "void*" and "uint16_t" and include
(assume void* is 32 bits)
struct s1 { void *next; uint16_t mode; char dat6[6]; };
struct s2 { void *next; uint16_t mode; char dat2[2];
uint64_t arr[5000000]; };
union us1s2 { struct s1 v1; struct s2 v2; };
Assume code will need to hold 500000 instances of s1, and 10 of s2.
Placing "next" and "mode" in a structure would impose a 33% space penalty
on the 500000 instances of struct s1 (and also impair data exchange with
any pre-existing code that that expects s1 to be laid out as above). And
constructing a us1s2 for every instance of s1 that code needs would impose
a many-orders-of-magnitude space penalty.
So how should code practically be written so as to avoid wasting space, or
is it no longer possible?
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-23 12:00 -0700 |
| Message-ID | <kfnwpi2cug8.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93955 |
supercat@casperkitty.com writes: > On Friday, September 23, 2016 at 10:52:42 AM UTC-5, Tim Rentsch >> Not if the uses must be done safely. Using unions to support >> common prefixing is a big PITA if what the Standard requires for >> such uses must be met. (And if being compiled as C++ is a >> consideration, then it can't be done at all.) > > What would be the purpose of specifying that the *complete* union > declaration be visible if not to make clear that an incomplete one > is not acceptable? [... more comments along those general lines ...] I don't know what the point of these comments is supposed to be. They seem to have no bearing on what I was saying.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-22 08:45 -0700 |
| Message-ID | <kfnzin0djkk.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93870 |
supercat@casperkitty.com writes: > The authors of the C99 Standard added a requirement that if a T1* > is used to access members of the common initial sequence of a T2, > then a declaration of a complete union type containing both T1 and > T2 must be visible to the compiler at the point where the objects > are used. You are confusing your understanding of what the various standards require and their authors' understanding of what they require. Between C89/C90 and C99, regarding this one point, there was a change to the text but not to what the standard requires, according to the understanding of the people who are the only people whose understanding counts in the matter. Compiler writers base their decisions on what WG14 say the requirements are, not on what self-appointed language lawyers say they are.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-22 09:36 -0700 |
| Message-ID | <a9907bfa-5ace-4d93-a9db-bcafbd4c6108@googlegroups.com> |
| In reply to | #93908 |
On Thursday, September 22, 2016 at 10:45:55 AM UTC-5, Tim Rentsch wrote: > supercat writes: > > The authors of the C99 Standard added a requirement that if a T1* > > is used to access members of the common initial sequence of a T2, > > then a declaration of a complete union type containing both T1 and > > T2 must be visible to the compiler at the point where the objects > > are used. > > You are confusing your understanding of what the various standards > require and their authors' understanding of what they require. > Between C89/C90 and C99, regarding this one point, there was a > change to the text but not to what the standard requires, according > to the understanding of the people who are the only people whose > understanding counts in the matter. Compiler writers base their > decisions on what WG14 say the requirements are, not on what > self-appointed language lawyers say they are. Are you suggesting that the people who voted on C89 decided that it should be a secret requirement which would be known to them alone until it was revealed in C99? Or perhaps some people wanted to include it in C89 but it would have gotten voted down, so they instead decided to omit the rule from the text that was being voted upon and figured they could retroactively pretend that the rule was approved? Unless the C89 and C99 Committees had the same membership, I would not regard the C99 Committee as an authority on what the C89 Committee voted on.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-23 12:06 -0700 |
| Message-ID | <kfnshsqcu63.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93911 |
supercat@casperkitty.com writes: > On Thursday, September 22, 2016 at 10:45:55 AM UTC-5, Tim Rentsch wrote: >> supercat writes: >>> The authors of the C99 Standard added a requirement that if a T1* >>> is used to access members of the common initial sequence of a T2, >>> then a declaration of a complete union type containing both T1 and >>> T2 must be visible to the compiler at the point where the objects >>> are used. >> >> You are confusing your understanding of what the various standards >> require and their authors' understanding of what they require. >> Between C89/C90 and C99, regarding this one point, there was a >> change to the text but not to what the standard requires, according >> to the understanding of the people who are the only people whose >> understanding counts in the matter. Compiler writers base their >> decisions on what WG14 say the requirements are, not on what >> self-appointed language lawyers say they are. > > Are you suggesting that the people who voted on C89 decided that it should > be a secret requirement which would be known to them alone until it was > revealed in C99? No. > Or perhaps some people wanted to include it in C89 but it would have gotten > voted down, so they instead decided to omit the rule from the text that was > being voted upon and figured they could retroactively pretend that the rule > was approved? No, I'm not suggesting that either. Do you enjoying thinking up these idiotic questions? I have no idea what other useful purpose they might be thought of as serving. > Unless the C89 and C99 Committees had the same membership, I would not > regard the C99 Committee as an authority on what the C89 Committee voted > on. There has been enough commonality and continuity of membership that I am confident the views on this point are not subtantially different between the times when C89 was adopted and when the changes in question were approved. But please feel free to check the membership rosters if you want to see for yourself.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-23 15:29 -0700 |
| Message-ID | <17ac35b9-7711-430f-af63-59ee9531058b@googlegroups.com> |
| In reply to | #93964 |
On Friday, September 23, 2016 at 2:06:53 PM UTC-5, Tim Rentsch wrote: > supercat writes: > > Are you suggesting that the people who voted on C89 decided that it should > > be a secret requirement which would be known to them alone until it was > > revealed in C99? > > No. > > > Or perhaps some people wanted to include it in C89 but it would have gotten > > voted down, so they instead decided to omit the rule from the text that was > > being voted upon and figured they could retroactively pretend that the rule > > was approved? > > No, I'm not suggesting that either. Prior to C89, compilers would essentially universally allow a pointer to one structure type to inspect the CIS of any other structure type. This has been a useful feature of the language since C74, and I've seen nothing in the text of C89 that would indicate an intention to change that. If the authors of C89 wanted to overturn 25 years of precedent, their failure to state such intention cannot plausibly be regarded as an oversight. Overtly stating such intention would have caused the Standard to be widely denounced. I can only see two plausible reasons why such intention was not stated: 1. They had no such intention, or 2. They deliberately wrote the Standard in a way that people would interpret as leaving precedents intact, so as to avoid denunciation. In either case, interpreting the Standard in a fashion consistent with precedent would be consistent with the *intent* of the authors, whether or not it matched their desires.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-29 07:56 -0700 |
| Message-ID | <kfnvaxeah6a.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93621 |
supercat@casperkitty.com writes: > On Friday, September 23, 2016 at 2:06:53 PM UTC-5, Tim Rentsch wrote: >> supercat writes: >>> Are you suggesting that the people who voted on C89 decided that it should >>> be a secret requirement which would be known to them alone until it was >>> revealed in C99? >> >> No. >> >>> Or perhaps some people wanted to include it in C89 but it would have gotten >>> voted down, so they instead decided to omit the rule from the text that was >>> being voted upon and figured they could retroactively pretend that the rule >>> was approved? >> >> No, I'm not suggesting that either. > > Prior to C89, compilers would essentially universally allow a pointer to > one structure type to inspect the CIS of any other structure type. By accident, not by design. > This has been a useful feature of the language since C74, It may have been a useful accident of history. It was not a feature of the language. > and I've seen nothing > in the text of C89 that would indicate an intention to change that. There was nothing to change. Lots of programmers took advantage of all kinds of dicey constructs in the early days of C, but most of those who did so knew they were skating on thin ice. In those days it was just more common to operate outside the bounds of how the language was defined. > If the authors of C89 wanted to overturn 25 years of precedent, their > failure to state such intention cannot plausibly be regarded as an > oversight. There was no precedent to overturn. > Overtly stating such intention would have caused the Standard > to be widely denounced. I can only see two plausible reasons why such > intention was not stated: > > 1. They had no such intention, or > > 2. They deliberately wrote the Standard in a way that people would > interpret as leaving precedents intact, so as to avoid denunciation. > > In either case, interpreting the Standard in a fashion consistent with > precedent would be consistent with the *intent* of the authors, whether > or not it matched their desires. Again, there was no precedent. You are seeing phantoms. You really should learn to deal with the fact that your perceptions of reality are in many cases in conflict with others' perceptions of reality, as has been evidenced many times in responses to your postings in the newsgroup here. (My apologies if this ends up being posted twice. I got a strange error message from my newsreader.)
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-30 10:54 -0700 |
| Message-ID | <05de4ed0-61b7-402e-91e6-cc4cd18069fa@googlegroups.com> |
| In reply to | #94241 |
On Thursday, September 29, 2016 at 9:56:23 AM UTC-5, Tim Rentsch wrote:
> supercat writes:
> > Prior to C89, compilers would essentially universally allow a pointer to
> > one structure type to inspect the CIS of any other structure type.
>
> By accident, not by design.
Why do you keep claiming that behavior which was useful, greatly
facilitated compatibility with existing code (including code going back
to the days of B), and would for many years cost *nothing* to support,
must have been accidental?
> > This has been a useful feature of the language since C74,
>
> It may have been a useful accident of history. It was not a feature
> of the language.
The 1974 specification describes the behavior of "->" and "." in terms of
memory offsets. In what sense does that not make such behaviors "a feature
of the language"?
> > and I've seen nothing
> > in the text of C89 that would indicate an intention to change that.
>
> There was nothing to change. Lots of programmers took advantage
> of all kinds of dicey constructs in the early days of C, but most
> of those who did so knew they were skating on thin ice. In those
> days it was just more common to operate outside the bounds of
> how the language was defined.
The constructs were unambiguously defined in B, and described in C74 as
being analogous to the constructs in B but with the addition of member
types. What is the earliest evidence you can find to suggest that given
struct ST { ... MT m; ... } *p;
the expression ((struct ST*)p)->m was intended to have a meaning different
from:
*((MT*)(offsetof(struct ST, m) + (char*)p))
> > If the authors of C89 wanted to overturn 25 years of precedent, their
> > failure to state such intention cannot plausibly be regarded as an
> > oversight.
>
> There was no precedent to overturn.
Useful code which employs a construct is precedent. Such code existed, and
the authors of the Standard cannot have been unaware of it.
> You really should learn to deal with the fact that your
> perceptions of reality are in many cases in conflict with
> others' perceptions of reality, as has been evidenced many
> times in responses to your postings in the newsgroup here.
They certainly disagree with your perceptions of reality.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-09-30 11:18 -0700 |
| Message-ID | <5dbd8c3a-110c-4b6c-8d3b-66e5486f2d32@googlegroups.com> |
| In reply to | #94315 |
On Friday, September 30, 2016 at 2:55:12 PM UTC-3, >
...
> > This has been a useful feature of the language since C74,
> >
> > It may have been a useful accident of history. It was not a feature
> > of the language.
>
> The 1974 specification describes the behavior of "->" and "." in terms of
> memory offsets. In what sense does that not make such behaviors "a feature
> of the language"?
>
>
> > > and I've seen nothing
> > > in the text of C89 that would indicate an intention to change that.
> >
> > There was nothing to change. Lots of programmers took advantage
> > of all kinds of dicey constructs in the early days of C, but most
> > of those who did so knew they were skating on thin ice. In those
> > days it was just more common to operate outside the bounds of
> > how the language was defined.
>
> The constructs were unambiguously defined in B, and described in C74 as
> being analogous to the constructs in B but with the addition of member
> types. What is the earliest evidence you can find to suggest that given
>
> struct ST { ... MT m; ... } *p;
>
> the expression ((struct ST*)p)->m was intended to have a meaning different
> from:
>
> *((MT*)(offsetof(struct ST, m) + (char*)p))
>
> > > If the authors of C89 wanted to overturn 25 years of precedent, their
> > > failure to state such intention cannot plausibly be regarded as an
> > > oversight.
I tried to find some references about C history, but it's hard because it's too old.
What I would like to understand is why the operator -> was created and not just ".".
void F(struct X* p)
{
p.x = 1; //why not? p cannot have members
}
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-09-30 19:26 +0100 |
| Message-ID | <nsmaoa$sa0$1@dont-email.me> |
| In reply to | #94316 |
On 30/09/2016 19:18, Thiago Adams wrote:
> On Friday, September 30, 2016 at 2:55:12 PM UTC-3, >
>
> What I would like to understand is why the operator -> was created and not just ".".
>
> void F(struct X* p)
> {
> p.x = 1; //why not? p cannot have members
> }
This is a rare decision in C that I agree with. In C:
A[i]; // A could be an array, or a pointer (not to the array
// but to one of its elements)
f(); // f could be a function, or pointer to function
And now you're proposing this:
p.m; // p could be a struct, or a pointer to struct
How about keeping the language transparent?
But if .m can only used with actual structs, then (*p).m needs to be
written when p is a pointer. That's too much so -> was introduced (or
that's what everyone uses it for anyway).
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-30 12:41 -0700 |
| Message-ID | <0c8edb5f-6e3f-4b75-900d-bc23b9369ec3@googlegroups.com> |
| In reply to | #94316 |
On Friday, September 30, 2016 at 1:19:03 PM UTC-5, Thiago Adams wrote: > What I would like to understand is why the operator -> was created and > not just ".". The "->" operator is inherited from the language B. In that language, pointers were required to be the same size as integers and hold addresses, and variables would be interpreted as a pointers or integers based upon context. B didn't have variables of structure type, but did have syntax to define symbols at consecutive addresses starting with zero, and it did have a syntax to reserve a specified number of words *at compile time* and cause a variable to be pre-loaded with the address of that storage. The syntax x->y would cause the value *stored at* the address given by x to be added to the value of symbol y, and access the word at the resulting address. That was distinct from x[y] which would add the value stored at the address given by x to the value stored at the address given by y, and access the word at the resulting address. Beyond the fact that x->y existed in B, it is useful because the indirection operator uses prefix syntax but member access uses postfix, meaning that *x.y would have two reasonable meanings: - Evaluate x.y and apply the indirection operator to that - Evaluate (*x) and apply the member-access operator to that. Having different operators for the two distinct meanings is cleaner than requiring parentheses when using at least one of them.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-30 21:07 +0100 |
| Message-ID | <87lgy96tjv.fsf@bsb.me.uk> |
| In reply to | #94325 |
supercat@casperkitty.com writes: <snip> > Beyond the fact that x->y existed in B, What is your reference for this? I had to program in B for while and I have no memory of that. What's more (since my memory is hardly reliable these days), I can't find it in the manual I have. <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-09-30 23:30 -0700 |
| Message-ID | <59871cf8-10b7-4a12-9aa3-c088deb73f3d@googlegroups.com> |
| In reply to | #94315 |
On Friday, September 30, 2016 at 6:55:12 PM UTC+1, supe...@casperkitty.com wrote:
>
> The 1974 specification describes the behavior of "->" and "." in terms of
> memory offsets. In what sense does that not make such behaviors "a
> feature of the language"?
>
It was, in 1974.
If we declared struct point2 {double x, double y}
then x was declared as "offset 0 bytes" and y as "offset 8 bytes", in
a "struct member" namespace.
We could then declare struct point3 {double x, double y, double z }
Then the function
double ydist( *a, *b)
{
return fabs(a->y - b->y);
}
was well-formed and defined. (Not sure what the types of the pointers
were supposed to be).
However the snag was that if we then did
struct character_histrogram
{
int a; /* count of a s*/
...
int x;
int y;
int z;
}
it would break, because the members would clash. That proved to be
too much of a nuisance as programs got bigger.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-10-01 11:35 +0100 |
| Message-ID | <87ponk5pcg.fsf@bsb.me.uk> |
| In reply to | #94347 |
I offer only a tidy-up...
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
<snip>
> ... in 1974.
>
> If we declared struct point2 {double x, double y}
s/,/;/
> then x was declared as "offset 0 bytes" and y as "offset 8 bytes", in
> a "struct member" namespace.
Both also had associated types.
> We could then declare struct point3 {double x, double y, double z }
s/,/;/g
It's worth pointing out that what matter here is that the type and
offset of x and y match those of the previous struct.
> Then the function
>
> double ydist( *a, *b)
> {
> return fabs(a->y - b->y);
> }
>
> was well-formed and defined. (Not sure what the types of the pointers
> were supposed to be).
The pointers could be of any type and the syntax was like this (using
char * as an extreme example):
double ydist(a, b)
char *a, *b;
{
return fabs(a->y - b->y);
}
> However the snag was that if we then did
>
> struct character_histrogram
> {
> int a; /* count of a s*/
> ...
> int x;
> int y;
> int z;
> }
>
> it would break, because the members would clash.
Just to be clear, the clash could come from either a mismatch of type or
of offset withing the struct. Here you have (as far as 1974 C is
concerned) done both, so it's not clear that either would be a problem.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-10-01 14:44 -0700 |
| Message-ID | <ad83486a-338c-4546-801d-e5bde0ee06a5@googlegroups.com> |
| In reply to | #94347 |
On Saturday, October 1, 2016 at 1:30:22 AM UTC-5, Malcolm McLean wrote:
> However the snag was that if we then did
>
> struct character_histrogram
> {
> int a; /* count of a s*/
> ...
> int x;
> int y;
> int z;
> }
>
> it would break, because the members would clash. That proved to be
> too much of a nuisance as programs got bigger.
Until C started regarding structures as having separate namespaces, it
was common for structure member names to include an abbreviation of the
structure type to minimize such conflicts; the later rules are semantically
equivalent to having the compiler prefix each member name with an identifier
for the structure type when generating its definition, and again when using
the "." or "->" operator, thus eliminating the need to have the programmer
do so.
I'm curious when it was decided that structure types should be considered
relevant for purposes other than storage allocation and name lookup. The
authors of the Standard didn't want to brand as non-compliant a compiler
which varied the alignment rules for arrays according to the number of
elements (which on some platforms could be a useful optimization) but on
platforms that didn't do such a thing I think it would have been recognized
as useful to be able to do something like:
struct counted_array { int size; float arr[0]; }
struct counted_array1 { int size; float arr1[1]; }
struct counted_array4 { int size; float arr4[4]; }
struct counted_array8 { int size; float arr8[8]; }
and then be able to have a function which could treat a pointer to any of
those types as a pointer to a "counted_array" [note that code using any of
those types wouldn't need to use separate names for the array member, since
"arr" would be at the correct offset]. While such an approach would not
have been workable on all machines, it could save a lot of code on those
machines where it would work. (I'm not sure if c74 would have accepted
the declaration if it had used the same name for every array-type member;
I suspect it probably would have since it wouldn't have needed to remember
the size of any array once it had computed the size of the structure in
which it appeared).
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-09-14 22:56 +0100 |
| Message-ID | <nrch1q$kee$1@dont-email.me> |
| In reply to | #93491 |
On 14/09/16 22:20, Thiago Adams wrote:
> On Wednesday, September 14, 2016 at 5:50:50 PM UTC-3, Richard
> Heathfield > Did you mean TypeSpecifier? In my experience,
> mis-spellings are best
>> corrected sooner rather than later, before they pollute the whole
>> code base.
>
> Yes!
>
>> Why not just:
>>
>> SimpleTypeSpecifer * p = malloc(sizeof *p);
>
> I use visual C++, and I compile the same code in C and C++. For the
> Microsoft compilers, the C++ version is usually better. (Produces
> more error messages and faster exe) So the "C/C++ version" requires
> more casts.
Um, okay, can we just take it as read that I'm wearing a mean, frowning
expression, and leave it at that? I doubt very much whether I'd change
your mind. But if it were me, I'd implement it as a C library, compile
it under C rules, and then use C++'s "extern C" thing to link it in.
>
> But this: SimpleTypeSpecifer * p = (SimpleTypeSpecifer *)
> malloc(sizeof *p);
>
> works. I liked it.
>
>> You forgot something important. This should be:
>>
>> if(p != NULL) { p->object.type = type; }
>>
>>> return p; }
>
> Yes. This would be my next question. How do you handle memory failure
> in your programs.
Let the caller decide. Always. A library routine should detect memory
failure and report it to the caller. It should never arbitrarily abort,
and it should never ignore the possibility of failure. The caller knows
far better than you do what the library is being used for (even -- and
perhaps especially -- if the caller is being written /by you/, six
months from now).
> This is a parser program. Probably the best thing to do is exit on
> memory failure. But I may regret this decision in the future.
Well, if the parser program wants to bomb out, if that's the most
sensible thing to do in the circumstances, fair enough. But let the
parser program code decide that. Don't leave it up to the library function.
>> This seems like a lot of trouble to take over types. Why not just
>> trust that the user-programmer knows what type he put into the
>> array, and that he'll know to take that type out again?
>
> This is a runtime problem. Nobody knows what the types are there...we
> need some runtime "id" and them cast. This will be AST for the C
> language. I need visit the nodes after.
>
> But the question is general. If you need 0..N shapes and a shape can
> be rectangle , circle or ellipse how would you do?
Firstly, I'd re-define N so that I needed 0..N-1 shapes! :-) And then
I'd define a shape to be an "array" (dynamically allocated, of course)
of arcs and lines (possibly even Bezier splines), with the number of
elements in the array stored alongside the array itself. Then drawing a
shape consists of
for(side = 0; side < p->numelems; side++)
{
drawcurve(context, p->shape[side]);
}
where p->shape[side] is an object that describes a curve (which can of
course be a straight line, i.e. a curve with 0 curvature).
If you do it that way, there's no reason why the data structure needs to
know what kind of shape it's storing.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-15 13:19 +0200 |
| Message-ID | <nre03e$8m7$1@dont-email.me> |
| In reply to | #93501 |
On 14/09/16 23:56, Richard Heathfield wrote:
> On 14/09/16 22:20, Thiago Adams wrote:
>> On Wednesday, September 14, 2016 at 5:50:50 PM UTC-3, Richard
>> Heathfield > Did you mean TypeSpecifier? In my experience,
>> mis-spellings are best
>>> corrected sooner rather than later, before they pollute the whole
>>> code base.
>>
>> Yes!
>>
>>> Why not just:
>>>
>>> SimpleTypeSpecifer * p = malloc(sizeof *p);
>>
>> I use visual C++, and I compile the same code in C and C++. For the
>> Microsoft compilers, the C++ version is usually better. (Produces
>> more error messages and faster exe) So the "C/C++ version" requires
>> more casts.
>
> Um, okay, can we just take it as read that I'm wearing a mean, frowning
> expression, and leave it at that? I doubt very much whether I'd change
> your mind. But if it were me, I'd implement it as a C library, compile
> it under C rules, and then use C++'s "extern C" thing to link it in.
>
The obvious alternative would be to write the whole thing in C++ rather
than C, and use a class hierarchy rather than a DIY solution with
unions, enums, etc.
You might still frown - after all, recommending C++ is blasphemy in
c.l.c - but at least the language and the compiler would be consistent.
(And don't newer versions of MSVS use clang for C, which is a perfectly
good C tool?)
>>
>> But this: SimpleTypeSpecifer * p = (SimpleTypeSpecifer *)
>> malloc(sizeof *p);
>>
>> works. I liked it.
>>
>>> You forgot something important. This should be:
>>>
>>> if(p != NULL) { p->object.type = type; }
>>>
>>>> return p; }
>>
>> Yes. This would be my next question. How do you handle memory failure
>> in your programs.
>
> Let the caller decide. Always. A library routine should detect memory
> failure and report it to the caller. It should never arbitrarily abort,
> and it should never ignore the possibility of failure. The caller knows
> far better than you do what the library is being used for (even -- and
> perhaps especially -- if the caller is being written /by you/, six
> months from now).
>
>> This is a parser program. Probably the best thing to do is exit on
>> memory failure. But I may regret this decision in the future.
>
> Well, if the parser program wants to bomb out, if that's the most
> sensible thing to do in the circumstances, fair enough. But let the
> parser program code decide that. Don't leave it up to the library function.
>
In general, I agree. But you might argue that out-of-memory errors are
never going to happen in this program - it will always be run on systems
with more than enough memory. Thus checks for malloc failures are a bit
like checks for lightning strike on the machine - they are really
unlikely to happen, and if they /do/ happen, things have gone so badly
wrong that there is little you or the rest of the program can do about
it - letting the OS clear up the mess is fine. Thus there is little
point in writing extra code to handle cases that won't happen - it's
just more effort, more things to get wrong, and more things to test (and
lets face it - how many people properly test all code paths in their
error handling code?).
Of course, there is a big difference between code that is for a small
user application, and code that runs on a serious server process. And
if it is library code that could be used for either system, you have to
program for the most serious case.
[toc] | [prev] | [next] | [standalone]
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
Back to top | Article view | comp.lang.c
csiph-web