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 2 of 5 — ← Prev page 1 [2] 3 4 5 Next page →
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-09-16 09:36 -0700 |
| Message-ID | <e06bdc46-44cb-418e-8783-94c3147871f3@googlegroups.com> |
| In reply to | #93627 |
On Friday, September 16, 2016 at 12:35:10 PM UTC-3, Bart wrote:
> On 16/09/2016 15:27, Thiago Adams wrote:
> >
> > Probably I will do this: (maybe this is my last version before implement)
> >
> > Any suggestion is welcome.
> >
> >
> > typedef enum {
> > CatType,
> > BananaType,
> > AirplaneType
> > } Type;
> >
> > typedef struct
> > {
> > Type type;
> > int color;
> > } Banana;
> >
> > typedef struct
> > {
> > Type type;
> > int color;
> > } Cat;
> >
> > typedef struct TAirplane
> > {
> > Type type;
> > int color;
> > } Airplane;
> >
> >
> > typedef union {
> > Cat* pCat;
> > Banana* pBanana;
> > } Node2;
> >
> > typedef union {
> > Airplane* pAirplane;
> > Banana* pBanana;
> > } Node1;
> >
> > #define IS_TYPE(X, T) (((struct {Type type;}*) (&X))->type == T)
> >
> > int main()
> > {
> > Node1 node;
> > node.pAirplane = malloc(sizeof *node.pAirplane);
> > node.pAirplane->type = AirplaneType;
> >
> > if (IS_TYPE(node, AirplaneType))
> > {
> > //yes I am an airplane
> > }
> >
> > return 0;
> > }
>
> It looks good, especially with the short, snappy identifiers.
>
> However, you might consider taking the Type outside of the Airplane,
> Banana and Cat structs. After all each struct knows what it is!
>
> --
> Bartc
For the symbols, I think I will have a hash table pointing to the AST.
So, I am not sure now, if I will point to something that I need to check the type. So, for now, I left the type intrusive.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-09-20 12:59 -0700 |
| Message-ID | <8e6459ac-a363-487b-96d8-3585fad04dd5@googlegroups.com> |
| In reply to | #93639 |
After the second level of -> it was too complicated to identify what was "cast" and what was "child of", so, I gave up the union solution.
The syntax also was uncommon.
//All this line could be 1 pointer
p->Type1->Type2->Type3
Now, I will use typedefs but they will work like tips - No check at compile time.
For instance:
typedef enum
{
//...
TypeFuncVarDeclaration,
TypeAssertDeclaration
//...
} Type;
//Works as a "base class"
typedef struct
{
Type type;
} ObjectWithType;
typedef struct
{
Type type;
//more...
} TAssertDeclaration;
typedef struct
{
Type type;
//more...
} TFuncVarDeclaration;
//TAssertDeclaration | TFuncVarDeclaration
typedef ObjectWithType TDeclaration;
void TDeclaration_Delete(TDeclaration* pDeclaration);
I can add some run-time checks with asserts.
For instance:
void TDeclaration_Delete(TDeclaration* pDeclaration)
{
assert(pDeclaration->type = TypeFuncVarDeclaration ||
pDeclaration->type = TAssertDeclaration);
//...
}
------
So, what I would like of one "external type system check" was the ability
to check if the casts make sense at compile time.
TAssertDeclaration p = ...
(TDeclaration*) p2 = p; //OK
(TOther*) p2 = p; //ERROR
//@typedef TAssertDeclaration | TFuncVarDeclaration TDeclaration;
TDeclaration is a type with the intersection of TAssertDeclaration and TFuncVarDeclaration;
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-20 14:08 -0700 |
| Message-ID | <7ee4b7c9-5d16-40bf-acb0-738ae7e3bc86@googlegroups.com> |
| In reply to | #93867 |
On Tuesday, September 20, 2016 at 3:00:06 PM UTC-5, Thiago Adams wrote:
> Now, I will use typedefs but they will work like tips - No check at compile time.
>
> For instance:
> //Works as a "base class"
> typedef struct
> {
> Type type;
> } ObjectWithType;
>
> typedef struct
> {
> Type type;
> //more...
> } TAssertDeclaration;
>
> typedef struct
> {
> Type type;
> //more...
> } TFuncVarDeclaration;
At least among microcomputer programming circles code like the above would
have been considered non-controversial in the 1990s (I have no idea what
mainframe compilers were doing). 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. If compiler writers recognize that a major purpose of the
CIS was to allow code similar to what you show, and avoid making aliasing
assumptions if such a declaration is visible at *either* the places where the
type is used as a T1 or at places where it is used as a T2, the requirement
for a visible union declaration will not adversely affect the semantic
usefulness of the construct.
Unfortunately, the authors of gcc have no interest in supporting such
constructs except in "-fno-strict-aliasing" mode. While some people claim
the language never supported such constructs, they were supported in
commonplace implementations, and such support was semantically useful.
Today, however, code which relies upon such useful semantics is viewed by
compiler writers as "broken".
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2016-09-21 15:53 +1200 |
| Message-ID | <e4eei6Fm7t3U1@mid.individual.net> |
| In reply to | #93870 |
On 09/21/16 09:08 AM, supercat@casperkitty.com wrote:
> On Tuesday, September 20, 2016 at 3:00:06 PM UTC-5, Thiago Adams wrote:
>> Now, I will use typedefs but they will work like tips - No check at compile time.
>>
>> For instance:
>> //Works as a "base class"
>> typedef struct
>> {
>> Type type;
>> } ObjectWithType;
>>
>> typedef struct
>> {
>> Type type;
>> //more...
>> } TAssertDeclaration;
>>
>> typedef struct
>> {
>> Type type;
>> //more...
>> } TFuncVarDeclaration;
>
> At least among microcomputer programming circles code like the above would
> have been considered non-controversial in the 1990s (I have no idea what
> mainframe compilers were doing). 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.
The use of a containing union has also been around for decades; the X11
XEvent is a good example.
--
Ian
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-21 07:38 -0700 |
| Message-ID | <548c3be9-5c69-4362-b27c-707b738841be@googlegroups.com> |
| In reply to | #93871 |
On Tuesday, September 20, 2016 at 10:53:52 PM UTC-5, Ian Collins wrote: > > At least among microcomputer programming circles code like the above would > > have been considered non-controversial in the 1990s (I have no idea what > > mainframe compilers were doing). 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. > > The use of a containing union has also been around for decades; the X11 > XEvent is a good example. Are you referring to the practice of having a number of types that start with the same fields, and having a function receive a pointer to a "generic" object that starts with those fields? What role do you see the union as playing? If the structures have massively different sizes, it's not practical to require that all instances be declared as union instances, and the Standard does not in general allow a pointer to an object which is not a union instance to be cast to a pointer to a union type containing a member of that type. If there were a form of quasi-union type such that a pointer to any type could be cast to any quasi-union type with a member of that type, provided that the pointer was only used to access suitably- aligned members, that would fix a lot of semantic weaknesses, but at present C includes no such types.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2016-09-23 09:12 +1200 |
| Message-ID | <e4ivqhF9kntU1@mid.individual.net> |
| In reply to | #93876 |
On 09/22/16 02:38 AM, supercat@casperkitty.com wrote: > On Tuesday, September 20, 2016 at 10:53:52 PM UTC-5, Ian Collins wrote: >>> At least among microcomputer programming circles code like the above would >>> have been considered non-controversial in the 1990s (I have no idea what >>> mainframe compilers were doing). 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. >> >> The use of a containing union has also been around for decades; the X11 >> XEvent is a good example. > > Are you referring to the practice of having a number of types that start > with the same fields, and having a function receive a pointer to a "generic" > object that starts with those fields? Looking back to some old (early 90s) code, we used message structs in enums in the same way as XEvent. XEvent its self is quite old! > What role do you see the union as > playing? If the structures have massively different sizes, it's not > practical to require that all instances be declared as union instances, and > the Standard does not in general allow a pointer to an object which is not > a union instance to be cast to a pointer to a union type containing a > member of that type. Code had to work with any message, so enum size problem was moot. -- Ian
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-09-21 05:26 -0700 |
| Message-ID | <9179e698-fe07-416c-a885-cca3f6b5d606@googlegroups.com> |
| In reply to | #93870 |
On Tuesday, September 20, 2016 at 6:09:28 PM UTC-3, supe...@casperkitty.com wrote:
> On Tuesday, September 20, 2016 at 3:00:06 PM UTC-5, Thiago Adams wrote:
> > Now, I will use typedefs but they will work like tips - No check at compile time.
> >
> > For instance:
> > //Works as a "base class"
> > typedef struct
> > {
> > Type type;
> > } ObjectWithType;
> >
> > typedef struct
> > {
> > Type type;
> > //more...
> > } TAssertDeclaration;
> >
> > typedef struct
> > {
> > Type type;
> > //more...
> > } TFuncVarDeclaration;
>
> At least among microcomputer programming circles code like the above would
> have been considered non-controversial in the 1990s (I have no idea what
> mainframe compilers were doing). 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. If compiler writers recognize that a major purpose of the
> CIS was to allow code similar to what you show, and avoid making aliasing
> assumptions if such a declaration is visible at *either* the places where the
> type is used as a T1 or at places where it is used as a T2, the requirement
> for a visible union declaration will not adversely affect the semantic
> usefulness of the construct.
>
> Unfortunately, the authors of gcc have no interest in supporting such
> constructs except in "-fno-strict-aliasing" mode. While some people claim
> the language never supported such constructs, they were supported in
> commonplace implementations, and such support was semantically useful.
> Today, however, code which relies upon such useful semantics is viewed by
> compiler writers as "broken".
So, how to fix it?
I need to allocate these structures on the heap.
Can I allocate less memory than the union, If I promises that I will not change the type? See "ParseModified"
(Where XEvent is created, on the stack?)
typedef struct
{
int type;
} ObjectWithType;
typedef struct
{
int type;
//more...
} TAssertDeclaration;
typedef struct
{
int type;
//more...
} TFuncVarDeclaration;
typedef union
{
int type;
ObjectWithType ObjectWithType;
TAssertDeclaration AssertDeclaration;
TFuncVarDeclaration FuncVarDeclaration;
} Declaration;
//???
void ParseModified(Declaration** pp)
{
TFuncVarDeclaration * pFuncVarDeclaration = malloc(sizeof* pFuncVarDeclaration);
//I promise, I will not change the type
*pp = (Declaration*)pFuncVarDeclaration;
}
void Parse(Declaration** pp)
{
Declaration * pDeclaration = malloc(sizeof* pDeclaration);
//pDeclaration->FuncVarDeclaration = ...
*pp = pDeclaration;
}
int main()
{
Declaration* p;
Parse(&p);
return 0;
}
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-09-21 05:35 -0700 |
| Message-ID | <21a06cbd-1bc3-4fd0-a05a-9c7eecddb030@googlegroups.com> |
| In reply to | #93872 |
I am avoiding a non-intrusive type like this:
struct TypePtr
{
int type;
void *p;
};
struct TypePtr
{
int type;
union {
T1 *p1;
T2 *p2;
};
};
Because I will have two pointers pointing for the same object, and then the "type" will be duplicated.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-09-21 06:01 -0700 |
| Message-ID | <e90c387f-5e5a-4662-a542-659edce1f7a7@googlegroups.com> |
| In reply to | #93872 |
On Wednesday, September 21, 2016 at 1:26:35 PM UTC+1, Thiago Adams wrote:
> On Tuesday, September 20, 2016 at 6:09:28 PM UTC-3, supe...@casperkitty.com wrote:
>
> I need to allocate these structures on the heap.
>
> Can I allocate less memory than the union, If I promises that I will not change the type? See "ParseModified"
>
> (Where XEvent is created, on the stack?)
>
> typedef struct
> {
> int type;
> } ObjectWithType;
>
> typedef struct
> {
> int type;
> //more...
> } TAssertDeclaration;
>
>
Yes, but I'm not sure about unions.
The first field in a structure s guaranteed to be aligned with the structure
itself and be first in memory. Precisely so you can do that sort of thing.
Pass the data about as void *s, then when you need to retrieve, cast
to ObjectWithType, retrieve the type tag, then cast to whatever the
structure is identified as.
However if you declare a big union I'm not sure what happens if you also
declare a pointer to it that contains only one of the smaller members.
I suspect it will usually work but is formally forbidden.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-22 01:44 -0700 |
| Message-ID | <kfn8tukfhmp.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93872 |
Thiago Adams <thiago.adams@gmail.com> writes:
> [accomplishing type changing using a 'union' pattern]
>
> So, how to fix it?
>
> I need to allocate these structures on the heap.
I suggest following a pattern like the following. First,
the interface/header part:
/****************************************************/
/* Header file */
typedef enum object_type_encoding_e {
OT_bogus,
OT_Foo,
OT_Bas,
/*...etc...*/
OT_no_more_values
} object_type_encoding;
typedef struct object_s {
object_type_encoding type;
} *Object; /* This is the generic type */
typedef struct foo_s *Foo; /* These are subtypes */
typedef struct bas_s *Bas;
/*...etc...*/
/* 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; }
/*...etc...*/
struct foo_s {
struct object_s prefix;
unsigned florble;
/* ... */
}; /* An example subtype struct */
struct bas_s {
struct object_s prefix;
double blarble;
/* ... */
}; /* An example subtype struct */
/*...etc...*/ /* .. more of the above .. */
Next, an example of usage, and functions illustrating how new
instances are created and initialized.
/******************************************************/
/* .c file (or more, for the constructors, if wanted) */
int
example_usage( Object it ){
switch( it->type ){
case OT_Foo: return as_Foo(it)->florble;
case OT_Bas: return as_Bas(it)->blarble;
default: return -1;
}
}
#include <stdlib.h>
Object
new_Foo(){
Foo result = malloc( sizeof *result );
/* .. check for null return value .. */
result->prefix.type = OT_Foo;
result->florble = 0;
/* ... */
return &result->prefix;
}
Object
new_Bas(){
Bas result = malloc( sizeof *result );
/* .. check for null return value .. */
result->prefix.type = OT_Bas;
result->blarble = 0;
/* ... */
return &result->prefix;
}
/*...etc...*/
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.
As long as uses of the conversion functions are predicated on
the appropriate type tag being found, it's all type safe and
everything is copacetic. (Of course the constructor functions
have to put correct values in the type tag field of the struct
too.)
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-09-22 13:16 +0100 |
| Message-ID | <ns0i2u$nb8$1@dont-email.me> |
| In reply to | #93886 |
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
(presumably as being the lesser 'evil').
But unions result in less intrusion within the code.
(Also, depending on the actual arrangement, they can make it easier to
share common fields other than just .type.)
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-22 08:02 -0700 |
| Message-ID | <09902938-21f0-4c45-9d71-bde7b5398bd2@googlegroups.com> |
| In reply to | #93891 |
On Thursday, September 22, 2016 at 7:16:46 AM UTC-5, Bart wrote: > So you've got rid of unions by using casts everywhere instead > (presumably as being the lesser 'evil'). > > But unions result in less intrusion within the code. > > (Also, depending on the actual arrangement, they can make it easier to > share common fields other than just .type.) It's best to think of C as two languages--one which became popular in the 1990s because it was designed to allow a simple compiler to achieve decent performance on typical microcomputer and minicomputer platforms, and one which is designed for fancier compilers but only allows programmers to achieve desired semantics by expressing things in much clunkier fashion in the hopes that a compiler will turn them into something efficient. The techniques you like are supported by the former language, but not the latter. Note that gcc does not (as of 6.2) reliably handle code that uses memory as different types at different times *even in cases which are 100% unambiguously defined by the Standard*. If code can afford to use malloc and free every time memory is re-purposed, allowing a compiler to regard operations on different types as unsequenced relative to each other may sometimes offer useful performance gains. If achieving good performance would require repurposing memory, however, using -fno-strict-aliasing will be more reliable than trying to abide by the Standard and hope that gcc's optimization bugs don't break your code.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-09-22 11:44 -0700 |
| Message-ID | <lnvaxnvkp9.fsf@kst-u.example.com> |
| In reply to | #93898 |
supercat@casperkitty.com writes:
[...]
> Note that gcc does not (as of 6.2) reliably handle code that uses memory
> as different types at different times *even in cases which are 100%
> unambiguously defined by the Standard*.
Have you submitted a bug report (or can you cite an existing one)?
--
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 | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-22 09:52 -0700 |
| Message-ID | <233fb759-60f4-4113-ba1c-0949c8fdb924@googlegroups.com> |
| In reply to | #93909 |
On Thursday, September 22, 2016 at 10:49:09 AM UTC-5, Keith Thompson wrote: > supercat writes: > [...] > > Note that gcc does not (as of 6.2) reliably handle code that uses memory > > as different types at different times *even in cases which are 100% > > unambiguously defined by the Standard*. > > Have you submitted a bug report (or can you cite an existing one)? I've observed the behavior and posted about it here. People who actually use gcc may want to file a bug report. I do not believe it is possible, practical, or useful for a compiler to try to exploit every possible aliasing optimization which the Standard does not forbid. The easiest bug fix would be to have gcc apply a less aggressive form of optimization which would be compatible with a lot of code which otherwise requires -fno-strict-aliasing, but I see no reason to believe the authors of gcc are interested in such an approach. Aliasing bugs exist because the authors of gcc are taking rules that were written to facilitate simple optimizations and trying to use them in ways for which they were never designed, thus creating many more corner cases than the authors of the Standard could reasonably have intended. Even if the maintainers of gcc manage to fix many wrongly-handled cases I see no reason to believe they'll ever find them all.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-23 09:49 +0200 |
| Message-ID | <ns2mq7$bqh$1@dont-email.me> |
| In reply to | #93913 |
On 22/09/16 18:52, supercat@casperkitty.com wrote: > On Thursday, September 22, 2016 at 10:49:09 AM UTC-5, Keith Thompson wrote: >> supercat writes: >> [...] >>> Note that gcc does not (as of 6.2) reliably handle code that uses memory >>> as different types at different times *even in cases which are 100% >>> unambiguously defined by the Standard*. >> >> Have you submitted a bug report (or can you cite an existing one)? > > I've observed the behavior and posted about it here. People who actually > use gcc may want to file a bug report. > > I do not believe it is possible, practical, or useful for a compiler to > try to exploit every possible aliasing optimization which the Standard > does not forbid. The easiest bug fix would be to have gcc apply a less > aggressive form of optimization which would be compatible with a lot of > code which otherwise requires -fno-strict-aliasing, but I see no reason > to believe the authors of gcc are interested in such an approach. > > Aliasing bugs exist because the authors of gcc are taking rules that were > written to facilitate simple optimizations and trying to use them in ways > for which they were never designed, thus creating many more corner cases > than the authors of the Standard could reasonably have intended. Even > if the maintainers of gcc manage to fix many wrongly-handled cases I see > no reason to believe they'll ever find them all. > 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.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-23 07:55 -0700 |
| Message-ID | <58c2a8d6-5609-458e-93f9-0811123a96ff@googlegroups.com> |
| In reply to | #93930 |
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;
}
Since you wanted me to dig it up, here's the example I posted before.
https://godbolt.org/g/75oLGx
The visible pointer conversion I mention in the comments shouldn't affect
conformity (reading the variable to "temp" and writing it back in two
separate operations makes things defined regardless) but should provide a
second hint to the compiler that it should be cautious about trying to
cache values of type T1.
So there's a sample of buggy code. Similar thing can happen if there are
two structure types that have the same representation.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-24 16:29 +0200 |
| Message-ID | <ns62k1$i6j$1@dont-email.me> |
| In reply to | #93948 |
On 23/09/16 16:55, supercat@casperkitty.com wrote:
> 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;
> }
If T1 and T2 are compatible types (as might be the case, such as on
Windows), then the answer will be 2. If they are incompatible types,
such as on 64-bit Linux, the answer is undefined - you are trying to
access the same object through pointers to two incompatible types. Some
compiler and optimisation options will give 2, others will give 1,
others could, in theory, give something else - but I think that's
unlikely in practice.
gcc gives 1 with optimisation -O2 and above, on 64-bit Linux. There is
no bug here in gcc as far as I can see - your code is incorrect.
>
> Since you wanted me to dig it up, here's the example I posted before.
>
> https://godbolt.org/g/75oLGx
>
Maybe the link is not working as expected - it appeared to have the code:
// Type your code here, or load an example.
int square(int num) {
return num * num;
}
I don't see how this relates to your point.
> The visible pointer conversion I mention in the comments shouldn't affect
> conformity (reading the variable to "temp" and writing it back in two
> separate operations makes things defined regardless) but should provide a
> second hint to the compiler that it should be cautious about trying to
> cache values of type T1.
>
> So there's a sample of buggy code. Similar thing can happen if there are
> two structure types that have the same representation.
>
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-24 15:56 +0100 |
| Message-ID | <87twd5fitb.fsf@bsb.me.uk> |
| In reply to | #93977 |
David Brown <david.brown@hesbynett.no> writes:
> On 23/09/16 16:55, supercat@casperkitty.com wrote:
>> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
<snip>
>>> ... 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;
>> }
>
> If T1 and T2 are compatible types (as might be the case, such as on
> Windows), then the answer will be 2. If they are incompatible types,
> such as on 64-bit Linux, the answer is undefined - you are trying to
> access the same object through pointers to two incompatible types.
That's not a thing! There are rules about how you can access objects,
but they are much more complex that this summary and I'm not sure where
you think the violation occurs. Can you point to the line and give the
rule being broken?
> Some compiler and optimisation options will give 2, others will give
> 1, others could, in theory, give something else - but I think that's
> unlikely in practice.
>
> gcc gives 1 with optimisation -O2 and above, on 64-bit Linux. There
> is no bug here in gcc as far as I can see - your code is incorrect.
My gcc (5.2.1 20151010) gives 2 for all -Ox. Presumably you have a
newer version?
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-24 17:50 +0200 |
| Message-ID | <ns67c3$25n$1@dont-email.me> |
| In reply to | #93980 |
On 24/09/16 16:56, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
>
>> On 23/09/16 16:55, supercat@casperkitty.com wrote:
>>> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
> <snip>
>>>> ... 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;
>>> }
>>
>> If T1 and T2 are compatible types (as might be the case, such as on
>> Windows), then the answer will be 2. If they are incompatible types,
>> such as on 64-bit Linux, the answer is undefined - you are trying to
>> access the same object through pointers to two incompatible types.
>
> That's not a thing! There are rules about how you can access objects,
> but they are much more complex that this summary and I'm not sure where
> you think the violation occurs. Can you point to the line and give the
> rule being broken?
>
I am thinking of the rules in 6.5, paragraph 7 about how "an object
shall have its stored value accessed". It does not explicitly say that
accessing the same data through pointers to incompatible types is
undefined - but it is implicitly undefined behaviour by virtue of not
being defined behaviour.
But I could be wrong - and if this really is incorrect behaviour from
gcc, then it needs reported and fixed.
>> Some compiler and optimisation options will give 2, others will give
>> 1, others could, in theory, give something else - but I think that's
>> unlikely in practice.
>>
>> gcc gives 1 with optimisation -O2 and above, on 64-bit Linux. There
>> is no bug here in gcc as far as I can see - your code is incorrect.
>
> My gcc (5.2.1 20151010) gives 2 for all -Ox. Presumably you have a
> newer version?
>
I am testing here with <https://gcc.godbolt.org/> for convenience. It
is targeting 64-bit Linux, and the result is 1 for -O2 and above, on gcc
4.7 onwards. gcc 4.5 and 4.6 give 2. 64-bit versions of MIPS, PPC and
ARM also give 1, while all the 32-bit versions give 2 (which is to be
expected - on 32-bit targets, "int64_t" will be "long long int").
clang and icc both give 2 on the combinations I checked.
(I haven't run the code, but it's easy to see the value from the
assembly output.)
Note that the online compiler here is set up for C++ - you can use the
"-x c" flag to force C compilation.
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-09-24 13:45 -0400 |
| Message-ID | <0420caa0-b66b-bf32-d5e0-df864f463056@verizon.net> |
| In reply to | #93982 |
On 09/24/2016 11:50 AM, David Brown wrote:
> On 24/09/16 16:56, Ben Bacarisse wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>
>>> On 23/09/16 16:55, supercat@casperkitty.com wrote:
>>>> On Friday, September 23, 2016 at 2:49:43 AM UTC-5, David Brown wrote:
>> <snip>
>>>>> ... 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;
>>>> }
>>>
>>> If T1 and T2 are compatible types (as might be the case, such as on
>>> Windows), then the answer will be 2. If they are incompatible types,
>>> such as on 64-bit Linux, the answer is undefined - you are trying to
>>> access the same object through pointers to two incompatible types.
>>
>> That's not a thing! There are rules about how you can access objects,
>> but they are much more complex that this summary and I'm not sure where
>> you think the violation occurs. Can you point to the line and give the
>> rule being broken?
>>
>
> I am thinking of the rules in 6.5, paragraph 7 about how "an object
> shall have its stored value accessed". It does not explicitly say that
> accessing the same data through pointers to incompatible types is
> undefined - but it is implicitly undefined behaviour by virtue of not
> being defined behaviour.
4p2 says "Undefined behavior is otherwise indicated ... by the omission
of any explicit definition of the behavior". But you have to be careful
about applying that rule. Nowhere in the standard does it say explicitly
what the behavior of the expression 1+1 is if executed on Friday the
13th at 13:13:13. However, it does say "The result of the binary +
operator is the sum of the operands.". That applies regardless of what
the values of the operands are, and regardless of the time of day.
Therefore, there is no "omission of any explicit definition", just
because there is no mention of Friday the 13th. The definition of the
behavior covers the possibility of time-dependent behavior by failing to
mention any time dependence, rendering time-dependent behavior
impermissible.
There are rules defining the behavior when accessing the values stored
in objects through dereferenced pointers, and those rules continue to
apply regardless of whether other pointers of incompatible types were
also used to access those value - except when the behavior is explicitly
said to be undefined somewhere else. Therefore, there is no "omission of
any explicit definition".
6.5p7 does say that "An object shall have its stored value accessed only
by an lvalue expression that has one of the following types:", and it
lists 6 different possibilities. Violation of a "shall" that occurs
outside of a constraint clause renders the behavior undefined (4p2).
However, in every case, your code accesses the value stored in that
memory using an lvalue that qualifies according to the first item in
that list: "a type compatible with the effective type of the object".
That code accesses the object many times using an incompatible type, but
whenever it does so, it is writing a new value for the object. Those
accesses do not qualify as accessing the "stored value" of the object.
Every time that code accesses by reading the stored value, the read is
preceded by a write to that object through an lvalue of the same type as
the read. For an object with no declared type (which is what you create
by calling malloc()), the effective type is always the same as the type
of the last write to that memory through an lvalue that is not of
character type.
<pedantic>
There is one obscure case which is not covered by the first item on
6.5p7's list. If CHAR_BIT==64, it's possible for T2 to be a character
type. As a result, the effective type would only change as a result of
writing through lvalues with type T1. In that case, the first item on
the list for 6.5p7 doesn't apply when reading through lvalues of type
T2. Instead, the sixth item on that list applies: "a character type",
since that's what T2 is in that case.
</pedantic>
[toc] | [prev] | [next] | [standalone]
Page 2 of 5 — ← Prev page 1 [2] 3 4 5 Next page →
Back to top | Article view | comp.lang.c
csiph-web