<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'> > (of course the report also says that "The reference returned by NEW is distinct from all existing references")<BR> <BR>Aha. Good.<BR>And doesn't it seem kind of nice and correct if that same sort of thing applied to locals and globals?<BR>More consistent that way?<BR> <BR>Really I wouldn't mind if ARRAY [0..0] or ARRAY [0..-1] was just plain illegal.<BR>The following are not legal standard C/89/90:<BR>int a[-1];<BR>int a[0];<BR> <BR> <BR>Though int a[0] may be a popular extension -- in both gcc and Visual C++ -- and many other compilers are forced to follow their lead.<BR> <BR> <BR>I know we don't in general "do what C does" but C is not really a set of all bad decisions that should all be avoided, and in fact, Modula-3 is almost trivially isomorphic to C. The main differences are 1) it disallows some operations 2) it adds optional garbage collection via inserted barrier checks 3) generics and vtables which are a fairly simple layering 4) strict interface separation which is just enforcing what people can do do in C, but it is important that it is strict, since it allows for faster compilation.)<BR> <BR> <BR>In the face of my own ignorance, I think considering what C and C++ do is not a bad option. They avoid the existance of zero sized things. On the other hand, C++ compilers then do work hard to "reoptimize" because of this. By "reoptimize" I mean, removal of zero sized things can actually be a significant deoptimization, that you then have to be pretty clever to optimize..when..if only zero size was ok in the first place, it would have been easy to keep optimal.<BR>In particular:<BR> struct A { }; <BR> struct B : A { }; <BR> struct C : B { }; <BR> struct D : C { }; <BR> struct E : D { }; <BR> <BR> <BR>what is the sizeof(E)?<BR> If zero size was ok, then the sizeof(A) and B and C and D and E would all be zero and the compiler's  job would be easy. In reality keeping the sizeof(E) "small" isn't trivial.  Perhaps perhaps multiple inheritance is needed to make the point. Let's see..hm..I need to research this..the "empty base optimization"..the problem doesn't seem that bad..without multiple inherirtance, the size was only 1.<BR> <BR> <BR> struct A1 { }; <br> struct A2 { }; <BR> struct B1 : A1, A2 { }; <br> struct B2 : A1, A2 { }; <BR> struct C1 : B1, B2 { }; <br> struct C2 : B1, B2 { }; <BR> struct D : C1, C2 { }; <BR> struct E : D { }; <BR> <BR><br>extern int a = sizeof(E);<br><BR> <BR>Only with a "mess" could I blow it up e.g. 7:<BR> <BR> <BR>F:\>type 1.cpp && cl -c -FAsc 1.cpp && more 1.cod<br> struct A1 { };<br> struct A2 { };<BR> struct B1 : A1, A2 { };<br> struct B2 : A1, A2 { };<BR> struct C1 : B1, B2 { };<br> struct C2 : B1, B2 { };<BR> struct D : C1, C2 { };<BR> struct E : D { };<BR><br>extern int a = sizeof(E);<BR><br>Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.278 for x64<br>Copyright (C) Microsoft Corporation.  All rights reserved.<BR>1.cpp<br>; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.278<BR><br>include listing.inc<BR>INCLUDELIB LIBCMT<br>INCLUDELIB OLDNAMES<BR>PUBLIC  <a href="mailto:?a@@3HA">?a@@3HA</a>                                         ; a<br>_DATA   SEGMENT<br><a href="mailto:?a@@3HA">?a@@3HA</a> DD      07H                                     ; a<br>_DATA   ENDS<br>END<BR> <BR><br> <BR> <BR> - Jay<BR><br> <BR><div>> To: jay.krell@cornell.edu<br>> Date: Thu, 4 Oct 2012 13:37:33 -0700<br>> From: mika@async.caltech.edu<br>> CC: m3devel@elegosoft.com<br>> Subject: Re: [M3devel] zero sized structs?<br>> <br>> <br>> Well as a user I'm quite happy to see the two objects have different<br>> addresses, if it makes your life easier as a compiler writer.  However<br>> it's certainly not documented---so I'd better not depend on it!<br>> You're not supposed to be taking the ADR of stuff on the stack.<br>> It's UNSAFE, caveat emptor, etc...  I'm just saying that if you are<br>> doing that you're not writing programs that Modula-3 was intended for.<br>> If you want to pass something by reference, use VAR!<br>> <br>> I find that when you have trouble with zero-sized anything, you've usually<br>> used the wrong abstraction....  In any case the fact that the language<br>> allows certain things to be zero sized is very helpful when you are writing<br>> programs that have to generate Modula-3 code.  You don't have to keep<br>> track and insert dummies in various places.  But sure I can't think of any<br>> reason the compiler couldn't implement zero-sized things as being one-sized<br>> or four-sized, or whatever it/you want/s.  It looks like they take 16 bytes<br>> when you NEW them... (of course the report also says that "The reference<br>> returned by NEW is distinct from all existing references")<br>> <br>>      Mika<br>> <br>> <br>> Jay writes:<br>> >Same address & same size implies same object & same type. But the types can v=<br>> >ary. Please check also variables in sub-blocks. I think NT/x86 backend doesn=<br>> >'t always put them at same place. Then again, that is probably ok too -- in g=<br>> >eneral not all zero sized objects can be located -- they could be locals in d=<br>> >ifferent functions or globals in different modules.<br>> ><br>> ><br>> >You say use a different language, but 1) they are exceedingly rare so ok to w=<br>> >aste space 2) as small & simple Modula-3 is, it is still really isn't small o=<br>> >r simple, there are surprising number & level of detail to understand and de=<br>> >al with. Adding a notion of a zero sized thing isn't necessarily so obviousl=<br>> >y simple and free of complexity down the line.=20<br>> ><br>> ><br>> ><br>> > - Jay (briefly/pocket-sized-computer-aka-phone)<br>> ><br>> >On Oct 4, 2012, at 11:23 AM, <mika@async.caltech.edu> wrote:<br>> ><br>> >> It seems that CM3 puts them at the "same address"....<br>> >>=20<br>> >> UNSAFE MODULE Main;<br>> >> IMPORT IO, Fmt;<br>> >>=20<br>> >> TYPE<br>> >>   T =3D  ARRAY [1..-1] OF INTEGER;<br>> >>=20<br>> >> VAR t :=3D NEW(REF T); u :=3D NEW(REF T);<br>> >>    v : T;<br>> >>    w : T;<br>> >> BEGIN<br>> >>  IO.Put(Fmt.Int(LOOPHOLE(t,INTEGER), base :=3D 16) & "\n");<br>> >>  IO.Put(Fmt.Int(LOOPHOLE(u,INTEGER), base :=3D 16) & "\n");<br>> >>  IO.Put(Fmt.Int(LOOPHOLE(ADR(v),INTEGER), base :=3D 16) & "\n");<br>> >>  IO.Put(Fmt.Int(LOOPHOLE(ADR(w),INTEGER), base :=3D 16) & "\n");<br>> >> END Main.<br>> >>=20<br>> >> (114)async:~/ttt/src>../AMD64_LINUX/prog<br>> >> 2269030<br>> >> 2269040<br>> >> 602218<br>> >> 602218<br>> >>=20<br>> >> I don't see a problem with it.  Whoever thinks he needs to check whether<br>> >> ADR(v) equals ADR(w) should be using a different programming language...<br>> >>=20<br>> >>     Mika<br>> >>=20<br></div>                                     </div></body>
</html>