Topic: 1st member -> Struct
Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Wed, 2 Aug 2006 10:56:43 CST Raw View
kuyper@wizard.net wrote:
> skaller wrote:
> .
> > Well aliasing of unsigned char* has to work, right?
>
> 3.9.2p4 guarantees that "A cv-qualified or cv-unqualified (3.9.3) void*
> shall have the same representation and alignement requirements as a
> cv-qualified or cv-unqualified char*." There doesn't seem a similar
> statement covering unsigned char*,
>
Same representation doesn't mean that it can be aliased!
#include <iostream>
void assign(void** pp,void* p) {*pp=p;}
int main() {
char base_value0, base_value1, base_value2;
typedef char* base_type;
typedef void* alias_type;
base_type c=&base_value0;
void* first_p=&c;
void* other_p;
assign(&other_p,first_p);
alias_type* ap=static_cast<alias_type*>(other_p);
c=&base_value1;
*ap=&base_value2;
std::cout << (c==&base_value0) << (c==&base_value1) <<
(c==&base_value2);
}
I compiled with GCC 4.0.2 under GNU/Linux:
g++ -O1 alias_type_pointer.cpp && ./a.out && echo
Outputs:
001
g++ -O2 alias_type_pointer.cpp && ./a.out && echo
Outputs:
010
g++ -O2 -fno-strict-aliasing alias_type_pointer.cpp && ./a.out && echo
Outputs:
001
So, you see that a void* and a char* can't be aliased!
kuyper@wizard.net wrote:
> A garbage collector has to be familiar with all permitted
> representations of the pointer types it manages, which means that a
> significant portion of a garbage collector's code is inevitably
> implementation-specific.
>
Right... And a GC must also knows all the alignment requirements. Many
many platforms require that words be aligned... Not the x86 CPU... But
it's more the exception than the rule.
skaller wrote:
>Well aliasing of unsigned char* has to work, right?
>
>What else? presumably int* and unsigned* etc, since
>there is a constraint that values in the common subset
>of int and unsigned must have the same layout .. which
>would be useless unless this aliasing were permitted.
If you want to know aliasing rules, simply refer to the standard :
There is a paragraph which is meant to give which aliasing is
permitted.
"
3.10 Lvalues and rvalues
[basic.lval]
15If a program attempts to access the stored value of an object
through
an lvalue of other than one of the following types the behavior
is
undefined25):
_________________________
25) The intent of this list is to specify those circumstances in
which
--the dynamic type of the object,
--a cv-qualified version of the dynamic type of the object,
--a type that is the signed or unsigned type corresponding to
the
dynamic type of the object,
--a type that is the signed or unsigned type corresponding to a
cv-
qualified version of the dynamic type of the object,
--an aggregate or union type that includes one of the
aforementioned
types among its members (including, recursively, a member of a
sub-
aggregate or contained union),
--a type that is a (possibly cv-qualified) base class type of
the
dynamic type of the object,
--a char or unsigned char type.
_________________________
an object may or may not be aliased."
Well, that's exhaustive, all put in one paragraph and the footnote
explains the intent of this pargraph!
Now, don't say that the standard has not be well written. It's pretty
clear!
> Of course .. there are solutions, such as using a void*
> for ALL pointers and casting .. which of course not
> only makes the code unreadable .. it also defeats any
> of the optimisations the compiler might do on a type basis.
Yep : It forbids efficient pointer representations on platforms where
not all pointers have the same representation, and it inhibits
no-aliasing assumptions optimizations.
But if the standard said
" All pointers have the same representation & can be aliased "
These exact same optimizations would be inhibited : And for everybody!
So, I deem that we can't blame the standard here.
skaller wrote:
> As an example .. the Felix garbage collector calculates
> where pointers are in a struct, and chases them down,
> as garbage collectors do.
Garbage collectors are not portable.
It is possible to write GC for platforms where all the pointers have
the same representation : And binary compiled shared libraries
boundaries avoid aliasing problems.
These platforms are very common.... But why would the committee declare
illegal platforms where this doesn't hold true?
If you don't like these platforms .... Don't support them. Anyway, if
the committee choosed not to allow that, these platforms would probably
not support C++ at all, instead of giving very-inefficient dummy C++
implementations.
I mean : This implementation freedom is only a thing that increase the
portability of strictly-conforming code.
You can stick with a less good portability if you want, and use
implementation-specific but widely-available implementation details.
skaller, if you can't remember aliasing rules, I suggest you compile
your code under GCC (or a compiler having a similar option) with the
option -fno-strict-aliasing
It inhibits optimization, but at least, your code shall work correctly
(even though it is not perfectly portable).
skaller wrote:
> union {
> char *x;
> int *y;
> };
>
>
> int i = 1;
> int j;
> y = &i;
> j = *(int*)(void*)x;
This aliasing is illegal too...
But GCC allows that specifically (i.e. it inhibits aliasing
optimizations when one write to an union).
That GCC feature (non-portable) is meant to allow compilation of code
that use this widely-used (but non-portable) construct.
>From the g++ man page
"
-fstrict-aliasing
Allows the compiler to assume the strictest aliasing rules
applicable to the
language being compiled. For C (and C++), this activates
optimizations based
on the type of expressions. In particular, an object of one
type is assumed
never to reside at the same address as an object of a
different type, unless
the types are almost the same. For example, an "unsigned
int" can alias an
"int", but not a "void*" or a "double". A character type
may alias any other
type.
Pay special attention to code like this:
union a_union {
int i;
double d;
};
int f() {
a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than
the one most
recently written to (called ??type-punning??) is common.
Even with
-fstrict-aliasing, type-punning is allowed, provided the
memory is accessed
through the union type. So, the code above will work as
expected. However,
this code might not:
int f() {
a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
Every language that wishes to perform language-specific
alias analysis should
define a function that computes, given an "tree" node, an
alias set for the
node. Nodes in different alias sets are not allowed to
alias. For an example,
see the C front-end function "c_get_alias_set".
Enabled at levels -O2, -O3, -Os.
"
I know it's a bit off topic, but my point here was to show
1) Aliasing rules given by the standard
2) How a compiler (GCC) can handle the aliasing issue.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: skaller@users.sourceforge.net (skaller)
Date: Sun, 6 Aug 2006 04:24:36 GMT Raw View
On Wed, 02 Aug 2006 10:56:43 -0600, SuperKoko wrote:
> kuyper@wizard.net wrote:
>> skaller wrote:
>> .
>> > Well aliasing of unsigned char* has to work, right?
[]
> Same representation doesn't mean that it can be aliased!
Good point.
> Right... And a GC must also knows all the alignment requirements. Many
> many platforms require that words be aligned... Not the x86 CPU... But
> it's more the exception than the rule.
Mine doesn't know anything about alignment. The allocator needs
to know the maximum alignment. Perhaps you can explain what
it is you think the collector needs to know? It just follows
pointers in already allocated store. They're already aligned.
> If you want to know aliasing rules, simply refer to the standard :
Don't make me laugh too hard .. the Standard is a big document,
and things are often very hard to find in it, and even when
one does find a relevant clause there's no way to tell if it
is the only one, and finally .. you can't always be sure
what it is talking about, since many terms are overloaded,
poorly defined, or not defined at all.
> There is a paragraph which is meant to give which aliasing is
> permitted.
>
> "
> 3.10 Lvalues and rvalues
> [basic.lval]
> 15If a program attempts to access the stored value of an object
> through
> an lvalue of other than one of the following types the behavior
> is
> undefined25):
And what about rvalues?
> --the dynamic type of the object,
And what precisely is that?
> --a cv-qualified version of the dynamic type of the object,
>
> --a type that is the signed or unsigned type corresponding to
> the
> dynamic type of the object,
>
> --a type that is the signed or unsigned type corresponding to a
> cv-
> qualified version of the dynamic type of the object,
>
> --an aggregate or union type that includes one of the
> aforementioned
> types among its members (including, recursively, a member of a
> sub-
> aggregate or contained union),
>
> --a type that is a (possibly cv-qualified) base class type of
> the
> dynamic type of the object,
>
> --a char or unsigned char type.
>
> _________________________
> an object may or may not be aliased."
>
> Well, that's exhaustive, all put in one paragraph and the footnote
> explains the intent of this pargraph!
This clause says 'blah blah is undefined' and ALL
such statements are entirely without any normative content,
although they may indeed be useful :)
> So, I deem that we can't blame the standard here.
It's a tradeoff. Unspecified things allow compiler optimisations,
but can get in the way of the programmer.
> skaller wrote:
>> As an example .. the Felix garbage collector calculates
>> where pointers are in a struct, and chases them down,
>> as garbage collectors do.
>
> These platforms are very common.... But why would the committee declare
> illegal platforms where this doesn't hold true?
Committees do so all the time, sometimes they fail to constrain
when they should, and other times they overconstrain.
In this case it isn't clear to me what the advantages and
disadvantages of the different options actually are .. I won't
argue the specification is wrong (I just assumed something
unsupported by the Standard .. now I will just have to state
it as an assumption).
In other cases, it is clearer .. for example the
overconstraint on integer representations in C99
(which disallows many previously viable implementations).
> skaller, if you can't remember aliasing rules, I suggest you compile
> your code under GCC (or a compiler having a similar option) with the
> option -fno-strict-aliasing
> It inhibits optimization, but at least, your code shall work correctly
> (even though it is not perfectly portable).
So far it works perfectly anyhow. It isn't a matter of 'remembering'
the rules. The code is all generated by a translator:
Felix -> C++
The issue is how the translator handles certain things that
need to be handled. The harness which drives all this is utterly
aggressive with optimisations: there's no way I'm going to turn
them off.
> I know it's a bit off topic, but my point here was to show
> 1) Aliasing rules given by the standard
> 2) How a compiler (GCC) can handle the aliasing issue.
I don't see it as off topic: it's an example of how the
(deliberate) lack of specification in the Standard can and
is used by real compilers to perform optimisations. IMHO that
has everything to do with the precise specification given,
including what isn't specified -- and I thank you for
your time discussing it. FYI Felix also has aliasing rules,
and the Felix compiler is designed to be much more aggressive
optimising things than C/C++. For example the construction:
val x = 1;
is vaguely equivalent to C++ construction:
int const x = 1;
in that x is immutable. But unlike C/C++, in Felix the x
is not addressable, and therefore cannot be aliased,
at least not directly. Unfortunately, C/C++ concept of
const is too weak to allow aggressive optimisation:
a routine getting a pointer to const cannot cache
the value without further analysis, which may fail.
A stronger concept would be
int immutable x = 1;
int immutable *px = &x;
...
where immutable pointers cannot be converted to other kinds.
The values pointed at by such a pointer can be cached,
even if there is another one (such a pointer is equivalent
to a boxed value in a purely functional programming language).
--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: skaller@users.sourceforge.net (skaller)
Date: Sun, 6 Aug 2006 15:46:41 GMT Raw View
On Tue, 01 Aug 2006 11:43:12 -0600, kuyper wrote:
>
> skaller wrote:
>> On Sun, 30 Jul 2006 15:04:40 -0600, kuyper wrote:
>> What does it explain? Apart from the obvious fact I didn't
>> know what the Standard said .. :)
> That was, pretty much, what I meant by that comment. I get the
> impression that you know C pretty well, but aren't very clear about
> which of the things you know are guaranteed by the standard to be true
> for every conforming implmentation, and which are not.
I do understand the distinction (I was actually a member of WG21
in the past). True I haven't kept up .. and I doubt anyone knows
all the details -- or even where to find them -- including Bjarne.
Well perhaps Andrew Koenig does :)
Anyhow thanks for correcting me .. hmm .. now I'll have to go
fix the Felix docs, which list all the known departures from
the C++ Standard (one listed is in fact not a departure,
and a couple more things need to go on the list :)
Actually be interesting for some people to look at the code,
and/or the generator, see how many non-conforming things it
actually does: I would like to generate conforming code
where possible.
--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Sun, 6 Aug 2006 11:30:34 CST Raw View
skaller wrote:
> On Wed, 02 Aug 2006 10:56:43 -0600, SuperKoko wrote:
.
> > Right... And a GC must also knows all the alignment requirements. Many
> > many platforms require that words be aligned... Not the x86 CPU... But
> > it's more the exception than the rule.
>
> Mine doesn't know anything about alignment. The allocator needs
> to know the maximum alignment. Perhaps you can explain what
> it is you think the collector needs to know? It just follows
> pointers in already allocated store. They're already aligned.
What a GC needs to know depends upon how it works, and there's a lot of
different styles of GC out there. However, if it's going to be useful,
I believe that it needs to be able to recognise as such pointers into a
allocated piece of memory, even if those pointers have a different type
(and therefore possibly a different size, alignment, and
representation) from the one returned by the allocator. I don't see any
way to do that which doesn't rely heavily upon implementation-specific
knowledge.
.
> > 3.10 Lvalues and rvalues
> > [basic.lval]
> > 15If a program attempts to access the stored value of an object
> > through
> > an lvalue of other than one of the following types the behavior
> > is
> > undefined25):
>
> And what about rvalues?
The language doesn't provide mechanisms for accessing the stored value
of an object without the use of an lvalue. Any rvalues which are also
involved in the access (such as 'i' in array[i]) are not relevant to
the application of this rule.
> > --the dynamic type of the object,
>
> And what precisely is that?
Section 1.3.3: "the type of the most-derived object (1.8) to which the
lvalue denoted by an lvalue expression refers." You'll have to follow
up to the cross-reference to section 1.8 to really understand that
definition.
.
> > Well, that's exhaustive, all put in one paragraph and the footnote
> > explains the intent of this pargraph!
>
> This clause says 'blah blah is undefined' and ALL
> such statements are entirely without any normative content,
> although they may indeed be useful :)
As far as standardese is concerned, they are normative. However, in the
ordinary English meaning of the word, you're right, they are not. It
would be more accurate to describe them as relaxing the normative
content of statements made elsewhere. Because the behavior of such code
is undefined, most of the normative statements made elsewhere in the
standard that might otherwise apply, don't apply to such code.
Also, you can combine the normative statement "This program should
perform a specific task", with the informative statement "code with
feature X has undefined behavior" to derive the normative conclusion
"this program should not have feature X".
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Sun, 6 Aug 2006 11:31:39 CST Raw View
skaller wrote:
> On Wed, 02 Aug 2006 10:56:43 -0600, SuperKoko wrote:
> > Right... And a GC must also knows all the alignment requirements. Many
> > many platforms require that words be aligned... Not the x86 CPU... But
> > it's more the exception than the rule.
>
> Mine doesn't know anything about alignment. The allocator needs
> to know the maximum alignment. Perhaps you can explain what
> it is you think the collector needs to know? It just follows
> pointers in already allocated store. They're already aligned.
>
Ah, ok, you're right, that's a possibility...
But in that case, on x86, your GC will require that programmers align
correctly pointers.
i.e. the programmer will have to pass a flag for his compiler, saying
that all structures are aligned.
Otherwise, structures such as:
struct X {
char c;
void* p;
};
Might leads to problem (your GC will think that the pointed-to data is
not referenced while it is).
So your GC is not portable, anyway, since we can't portably assume that
every object is aligned in memory.
And space efficiency is often a good reason for having unaligned
things.
Note also, that with a x86 compiler, malloc might return "unaligned"
memory, since this CPU has no alignment requirement.
> > If you want to know aliasing rules, simply refer to the standard :
>
> Don't make me laugh too hard .. the Standard is a big document,
> and things are often very hard to find in it, and even when
> one does find a relevant clause there's no way to tell if it
> is the only one, and finally .. you can't always be sure
> what it is talking about, since many terms are overloaded,
> poorly defined, or not defined at all.
>
> > There is a paragraph which is meant to give which aliasing is
> > permitted.
> >
> > "
> > 3.10 Lvalues and rvalues
> > [basic.lval]
> > 15If a program attempts to access the stored value of an object
> > through
> > an lvalue of other than one of the following types the behavior
> > is
> > undefined25):
>
> And what about rvalues?
>
Well, there is no issue with rvalues.
Here, the UB happens when converting a lvalue (whose static type
differs from its dynamic type) to a rvalue.
A rvalue is already a rvalue... Thus, there is no rvalue-to-rvalue
conversion.
And even if there were such conversion, there would be no problem since
the dynamic type of a rvalue is always equal to its static type.
mhhh, you can convert from one rvalue of a type, to a rvalue of a
different type.
In that case, you should refer to the "Standard conversions" chapter.
> > --the dynamic type of the object,
>
> And what precisely is that?
>
Ok, this paragraph is not sufficient (though dynamic type and static
type are two notions that any good C++ programmer should know).
"
1.3.12 static type [defns.static.type]
the type of an expression (3.9), which type results from analysis of
the program without considering execution semantics.
The static type of an expression depends only on the form of the
program in which the expression appears, and does not
change while the program is executing.
1.3.4 dynamic type [defns.dynamic.type]
the type of the most derived object (1.8) to which the lvalue denoted
by an lvalue expression refers. [ Example: if a
pointer (8.3.1) p whose static type is "pointer to class B" is
pointing to an object of class D, derived from B (clause 10),
the dynamic type of the expression *p is "D." References (8.3.2)
are treated similarly. -end example ] The dynamic
type of an rvalue expression is its static type.
"
> > I know it's a bit off topic, but my point here was to show
> > 1) Aliasing rules given by the standard
> > 2) How a compiler (GCC) can handle the aliasing issue.
>
> I don't see it as off topic: it's an example of how the
> (deliberate) lack of specification in the Standard can and
> is used by real compilers to perform optimisations. IMHO that
> has everything to do with the precise specification given,
> including what isn't specified -- and I thank you for
> your time discussing it. FYI Felix also has aliasing rules,
> and the Felix compiler is designed to be much more aggressive
> optimising things than C/C++. For example the construction:
>
> val x = 1;
>
> is vaguely equivalent to C++ construction:
>
> int const x = 1;
>
> in that x is immutable. But unlike C/C++, in Felix the x
> is not addressable, and therefore cannot be aliased,
> at least not directly. Unfortunately, C/C++ concept of
> const is too weak to allow aggressive optimisation:
> a routine getting a pointer to const cannot cache
> the value without further analysis, which may fail.
> A stronger concept would be
>
> int immutable x = 1;
> int immutable *px = &x;
> ...
>
> where immutable pointers cannot be converted to other kinds.
> The values pointed at by such a pointer can be cached,
> even if there is another one (such a pointer is equivalent
> to a boxed value in a purely functional programming language).
>
Well, the ultimate way to have very powerful optimizations is the
"restrict" keyword (available in C99 but not in standard C++).
Thanks to restrict, I can perfectly understand why some guys said
(before 1999) that Fortran "was faster than C because without
pointers".
This sentence is wrong and misleading... But it must be interpreted as:
In Fortan, all pointers (which are parameters of a function) are
restrict pointers
restrict is a powerful (but dangerous) tool. I don't know whether it'll
be added to C++0x
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: skaller@users.sourceforge.net (skaller)
Date: Sun, 30 Jul 2006 05:02:46 GMT Raw View
On Wed, 26 Jul 2006 14:24:21 +0000, Alf P. Steinbach wrote:
> * skaller:
>> All data pointers have the same size, namely:
>>
>> sizeof(void*)
>
> No, that's incorrect.
So you're saying this need not work:
union {
char *x;
int *y;
};
int i = 1;
int j;
y = &i;
j = *(int*)(void*)x;
?
In the int * must be no larger than the char*.
If it is smaller, the code above fails because the
char* includes bytes not in the int* and therefore
won't be a valid address.
I alias pointers all the time. I assumed it must work.
--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: jdennett@acm.org (James Dennett)
Date: Sun, 30 Jul 2006 05:23:30 GMT Raw View
skaller wrote:
> On Wed, 26 Jul 2006 14:24:21 +0000, Alf P. Steinbach wrote:
>
>> * skaller:
>
>>> All data pointers have the same size, namely:
>>>
>>> sizeof(void*)
>> No, that's incorrect.
>
> So you're saying this need not work:
>
> union {
> char *x;
> int *y;
> };
>
> int i = 1;
> int j;
> y = &i;
> j = *(int*)(void*)x;
>
> ?
Not speaking for Alf, but it need not work. It looks like
undefined behaviour to me. When reading from x, the compiler
is free to ignore writes to y (given the specific types of
x and y here). Moreover, x could indeed by larger than y,
and on word-addressable machines may reasonably be so.
That said, on Posixish or Windows machines, or any of the
32-bit embedded platforms on which I've worked, all pointers
are indeed the same size, so the only likely problem is that
an optimizer might use the assumed non-aliasing of the types
in question to produce faster code that doesn't do what you
expect.
> In the int * must be no larger than the char*.
> If it is smaller, the code above fails because the
> char* includes bytes not in the int* and therefore
> won't be a valid address.
>
> I alias pointers all the time. I assumed it must work.
I think that recent g++ compilers with strict aliasing enabled
are standard-conforming in this respect and lead to a lot of
mistaken assumptions being exposed.
-- James
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Frederick Gotham <fgothamNO@SPAM.com>
Date: Sun, 30 Jul 2006 14:35:17 CST Raw View
skaller posted:
>>> All data pointers have the same size, namely:
>>>
>>> sizeof(void*)
>>
>> No, that's incorrect.
>
> So you're saying this need not work:
>
> union {
> char *x;
> int *y;
> };
>
> int i = 1;
> int j;
> y = &i;
> j = *(int*)(void*)x;
>
> ?
>
> In the int * must be no larger than the char*.
Your code invokes undefined behaviour -- it is non-portable. Your code
makes the unfounded presumption that the initial common sequence of char*
and int* are indentical. Perhaps this is so on some systems, but the
Standard imposes no such restriction. It would be perfectly okay for a
system to tag the extra bytes at the beginning of the char*, rather than at
the end, and on such a system, checking the value of "x" would yield
garbage. (Not to mention the prohibition of reading a union member after
having previously written to a different member).
> If it is smaller, the code above fails because the
> char* includes bytes not in the int* and therefore
> won't be a valid address.
Hypothetical scenario:
If the extra bytes were to be stored at the end of the char*, I would
presume that these "extra bytes" would be all zero if the pointed-to-object
has the alignment of an int. No data would be lost.
> I alias pointers all the time. I assumed it must work.
Maybe you should go over all your code, (assuming you wish for it to be
portable of course), and re-write any snippets akin to what you posted
above.
If you want to store any object's address, then use a char* or a void*.
Don't presume that incompatible pointer types have an indentical initial
common sequence. Failing that, perhaps propose to the Standards Committee
that they impose a restriction whereby all pointer types have an indentical
common initial sequence... see how you get on.
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: skaller@users.sourceforge.net (skaller)
Date: Sun, 30 Jul 2006 20:05:56 GMT Raw View
On Sun, 30 Jul 2006 05:23:30 +0000, James Dennett wrote:
> skaller wrote:
>> I alias pointers all the time. I assumed it must work.
>
> I think that recent g++ compilers with strict aliasing enabled
> are standard-conforming in this respect and lead to a lot of
> mistaken assumptions being exposed.
Well aliasing of unsigned char* has to work, right?
What else? presumably int* and unsigned* etc, since
there is a constraint that values in the common subset
of int and unsigned must have the same layout .. which
would be useless unless this aliasing were permitted.
Smly const and non-const pointer? Of course for a sole
small variable, conversions are fine .. but within a larger
struct, it isn't tenable to copy stuff about just to
fool the type system.
As an example .. the Felix garbage collector calculates
where pointers are in a struct, and chases them down,
as garbage collectors do.
Of course this would fail utterly if any of these pointers
were different sizes .. the collector has no idea what
C/C++ type the pointed at object is (although it knows
where every pointer stored IN that object is located).
Of course .. there are solutions, such as using a void*
for ALL pointers and casting .. which of course not
only makes the code unreadable .. it also defeats any
of the optimisations the compiler might do on a type basis.
Hmm .. to think I thought C++ had problems as a target
language .. now I know why people are going for native
code and avoiding even C .. (given that its has a serious
lack of control structures for modern languages as well).
--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Sun, 30 Jul 2006 15:04:40 CST Raw View
skaller wrote:
> On Wed, 26 Jul 2006 14:24:21 +0000, Alf P. Steinbach wrote:
>
> > * skaller:
>
> >> All data pointers have the same size, namely:
> >>
> >> sizeof(void*)
> >
> > No, that's incorrect.
>
> So you're saying this need not work:
>
> union {
> char *x;
> int *y;
> };
>
> int i = 1;
> int j;
> y = &i;
> j = *(int*)(void*)x;
>
> ?
Correct. There's no guarantee that int* and char* even have the same
size, much less the same representation.
> In the int * must be no larger than the char*.
There's no guarantees on the relative sizes, either. On some real
machines char* is larger than int* because directly addressable memory
locatios are more than one byte apart. However, it would also be
perfectly legal for int* to be larger than char*.
> If it is smaller, the code above fails because the
> char* includes bytes not in the int* and therefore
> won't be a valid address.
>
> I alias pointers all the time. I assumed it must work.
That explains a lot. Just because something works on a given platform
doesn't mean that it's guaranteed to work on all platforms.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: jdennett@acm.org (James Dennett)
Date: Sun, 30 Jul 2006 20:42:26 GMT Raw View
skaller wrote:
> On Sun, 30 Jul 2006 05:23:30 +0000, James Dennett wrote:
>
>> skaller wrote:
>
>>> I alias pointers all the time. I assumed it must work.
>> I think that recent g++ compilers with strict aliasing enabled
>> are standard-conforming in this respect and lead to a lot of
>> mistaken assumptions being exposed.
>
> Well aliasing of unsigned char* has to work, right?
Yes, I believe that is guaranteed, and aliasing of plain
char* may well also be guaranteed. When I say aliasing
of those types, I should maybe say that an unsigned char
or char is considered to potentially alias any variable.
> What else? presumably int* and unsigned* etc, since
> there is a constraint that values in the common subset
> of int and unsigned must have the same layout .. which
> would be useless unless this aliasing were permitted.
I don't think you can store into an int* and then read
out via an unsigned* portably.
> Smly const and non-const pointer? Of course for a sole
> small variable, conversions are fine .. but within a larger
> struct, it isn't tenable to copy stuff about just to
> fool the type system.
>
> As an example .. the Felix garbage collector calculates
> where pointers are in a struct, and chases them down,
> as garbage collectors do.
As does a system I wrong for C a long time ago; it takes
care to use void*/unsigned char* for navigating memory,
but it does make the not-completely portable assumption
that read/writing any pointer via a void* works -- and
for the wide range of platforms on which it has been tested,
that seems fine. It's just not something that C or C++
standards guarantees -- but there are wide ranges of things
that are true for most mainstream implementations that are
outside of the standard's guarantees.
> Of course this would fail utterly if any of these pointers
> were different sizes .. the collector has no idea what
> C/C++ type the pointed at object is (although it knows
> where every pointer stored IN that object is located).
>
> Of course .. there are solutions, such as using a void*
> for ALL pointers and casting .. which of course not
> only makes the code unreadable .. it also defeats any
> of the optimisations the compiler might do on a type basis.
>
> Hmm .. to think I thought C++ had problems as a target
> language .. now I know why people are going for native
> code and avoiding even C .. (given that its has a serious
> lack of control structures for modern languages as well).
C++ does have many dark corners, and I think that the vast
majority of C++ programmers don't understanding the aliasing
rules. I can't say that I'm completely happy with my own
level of understanding; most code can be written so that
the questions don't arise, but sometimes we need to know
more, and it's not simple to find certainty with C++.
-- James
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Sun, 30 Jul 2006 16:41:54 CST Raw View
skaller wrote:
.
> Well aliasing of unsigned char* has to work, right?
3.9.2p4 guarantees that "A cv-qualified or cv-unqualified (3.9.3) void*
shall have the same representation and alignement requirements as a
cv-qualified or cv-unqualified char*." There doesn't seem a similar
statement covering unsigned char*,
> What else? presumably int* and unsigned* etc, since
> there is a constraint that values in the common subset
> of int and unsigned must have the same layout .. which
> would be useless unless this aliasing were permitted.
No, for that guarantee to be useful, it's sufficient that int* and
unsigned* be convertible to each other's types; it isn't necessary that
they have the same size, representation, or alignment requirements. I
don't know of any requirement by the standard that they be compatible
with each other, but I could have missed something.
> Smly const and non-const pointer?
There' you're on sounder ground. 3.9.2 guarantees that "Pointers to
cv-qualified and cv-unqualified versions(3.9.3) of layout-compatible
types shall have the same value representation and alignment
requirements (3.9)."
> As an example .. the Felix garbage collector calculates
> where pointers are in a struct, and chases them down,
> as garbage collectors do.
A garbage collector has to be familiar with all permitted
representations of the pointer types it manages, which means that a
significant portion of a garbage collector's code is inevitably
implementation-specific.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Mon, 31 Jul 2006 05:18:06 GMT Raw View
In article <pan.2006.07.29.16.59.20.548774@users.sf.net>, skaller
<skaller@users.sourceforge.net> writes
>In the int * must be no larger than the char*.
I do not think that is strictly true (though it is on all systems I have
used). A int* could be a fat pointer that included type info which is
tripped when converted to a void* and restored on being cast back. Note
that the rules require that a pointer be restored to its original type
before dereferencing (yes, there is also room for some extra choices in
C++ but none of those force void* to be the largest pointer type)
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: skaller@users.sourceforge.net (skaller)
Date: Tue, 1 Aug 2006 04:02:46 GMT Raw View
On Sun, 30 Jul 2006 15:04:40 -0600, kuyper wrote:
> skaller wrote:
>> I alias pointers all the time. I assumed it must work.
>
> That explains a lot.
What does it explain? Apart from the obvious fact I didn't
know what the Standard said .. :)
> Just because something works on a given platform
> doesn't mean that it's guaranteed to work on all platforms.
Of course, not one suggested that. I'm all in favour
of writing strictly conforming 100% portable code when
it is reasonable to do so, particularly as my application
is a C++ code generator, and I want the generated code
to work on as many platforms as possible.
The question seems to be whether it is possible at all,
given the (messy) set of rules in the Standard,
which neither provide good performance, nor sufficient
programmer control.
For example, full control of layout is easily obtained
by just working with byte arrays and casting --- with
some simple configuration checks, this can be made
quite portable. The problem with such a system is simply
that it doesn't play well with existing C/C++ code using
structs .. in such cases you have no choice but to access
them using standard C/C++ syntax.
I guess there is one good side to all this -- with some
work I can probably generate C/C++ that is faster than
any hand written C/C++ is likely to be.
--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Tue, 1 Aug 2006 11:43:12 CST Raw View
skaller wrote:
> On Sun, 30 Jul 2006 15:04:40 -0600, kuyper wrote:
>
> > skaller wrote:
>
> >> I alias pointers all the time. I assumed it must work.
> >
> > That explains a lot.
>
> What does it explain? Apart from the obvious fact I didn't
> know what the Standard said .. :)
That was, pretty much, what I meant by that comment. I get the
impression that you know C pretty well, but aren't very clear about
which of the things you know are guaranteed by the standard to be true
for every conforming implmentation, and which are not.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Fri, 28 Jul 2006 10:06:54 CST Raw View
Frederick Gotham wrote:
> Frederick Gotham posted:
>
> > Where you have a POD struct which consists of one sole member object,
> > the POD struct shall have the exact same size and alignment as the object
> > on its own.
>
>
> In fact, I would like it to hold true for non-POD's also:
>
> templat <>
> struct SoleMember<std::string> {
> std::string obj;
> };
>
That's already a bad idea for POD types, with the problem that it would
require the same pointer representation for void* and structures... And
the seriously reduced freedom for compiler alignment rules.
Hey, AFAIK, with Borland C++, sizeof(long double)==10, but when putting
it in a structure and passing the command line option saying to pack
structures on 4-bytes boundaries (for speed efficiency).
struct X {
long double x;
};
sizeof(X)==12
I think BC++ has done a good choice : sizeof(long double)==10 allows
the programmer to have a maximal space efficiency when it is needed.
When speed efficiency is required, aligned structs are the way to go.
But for non-POD types it would be an even worst idea... It would impose
a specific layout for non-POD types.
AFAIK, now, non-POD types can be implemented with an extraodinary
freedom.
For example, the commonly named Pimpl_ idiom, might be implemented
automatically by a C++ compiler (it can be useful to reduce binary
compatibility problems when shared libraries evolve).
So, this non-POD class:
class X {
private:
char x;
};
Would not work if the compiler choose to apply the Pimpl_ idiom.
Secondly, the benefit of this proposal for POD types is very small, but
for non-POD types there is no benefit....
Since:
class X {
private:
int x;
};
X x;
int y=reinterpret_cast<int&>(x); // Undefined behavior ... see
conv.lval.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: skaller@users.sourceforge.net (skaller)
Date: Wed, 26 Jul 2006 06:06:18 GMT Raw View
On Mon, 24 Jul 2006 14:36:53 +0000, Alf P. Steinbach wrote:
>> I have a proposal, and it's to do with the inverse of the above:
>>
>> Where you have a POD struct which consists of one sole member object,
>> the POD struct shall have the exact same size and alignment as the object
>> on its own.
[]
> It would require same pointer size for class type objects as for other
> objects. Because you can declare and use a pointer to an incomplete
> class type object, which might then turn out to have the same size and
> alignment as e.g. a single char. ENIAC chatters its relays and says no.
The problem you refer to does not exist. All data pointers have
the same size, namely:
sizeof(void*)
I agree with the proposal. I don't care if this breaks stupid
compilers. I'd also extend the idea to the related topic
covered in another post: layout compatibility of arrays
and structs whose elements all have the same type.
--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: alfps@start.no ("Alf P. Steinbach")
Date: Wed, 26 Jul 2006 14:24:21 GMT Raw View
* skaller:
> On Mon, 24 Jul 2006 14:36:53 +0000, Alf P. Steinbach wrote:
>
>>> I have a proposal, and it's to do with the inverse of the above:
>>>
>>> Where you have a POD struct which consists of one sole member object,
>>> the POD struct shall have the exact same size and alignment as the object
>>> on its own.
>
> []
>
>> It would require same pointer size for class type objects as for other
>> objects. Because you can declare and use a pointer to an incomplete
>> class type object, which might then turn out to have the same size and
>> alignment as e.g. a single char. ENIAC chatters its relays and says no.
>
> The problem you refer to does not exist.
See discussion below.
> All data pointers have the same size, namely:
>
> sizeof(void*)
No, that's incorrect. All data pointers must be representable as void*.
The standard specifies that "A void* shall be able to hold any object
pointer": it has to specify that explicitly because that guarantee does
/not/ hold for other pointer types.
The problem here is, however, not what the standard currently guarantees
and doesn't guarantee, it is what guarantees can be introduced without
breaking current code on certain architectures.
So it may be that you're correct that the problem does not currently
exist, and will not exist is future, but that can only be demonstrated
(to reasonable probability) by an exhaustive enumeration of current
compilers, showing that all of them use only a single data pointer size.
> I agree with the proposal. I don't care if this breaks stupid
> compilers.
Compilers aren't stupid... They're not intelligent enough to be stupid.
Not yet, anyway. ;-)
> I'd also extend the idea to the related topic
> covered in another post: layout compatibility of arrays
> and structs whose elements all have the same type.
For a given platform or set of platforms anything goes. But the
language must be platform-independent, except to the degree that it's
already limited to binary platforms with >=8 bit bytes. Language
extensions /are/ permitted by the standard, and AFAICS that solves the
practical problem.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 26 Jul 2006 14:26:17 GMT Raw View
skaller posted:
> All data pointers have
> the same size, namely:
>
> sizeof(void*)
I'm not sure what you're trying to say, but I believe you're incorrect.
The Standard guarantees that the following expression evaluates to "true":
sizeof(char*) == sizeof(void*)
However, the Standard provides no guarantee whatsoever that the following
expression evaluates to "true":
sizeof(char*) == sizeof(short*) == sizeof(int*) == sizeof(long*)
== sizeof(float*) == sizeof(double long*) == sizeof(std::string*)
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Michiel.Salters@tomtom.com
Date: Wed, 26 Jul 2006 09:26:03 CST Raw View
skaller wrote:
> The problem you refer to does not exist. All data pointers have
> the same size, namely:
>
> sizeof(void*)
Where's the normative wording that says so?
AFAIK, sizeof(T*) may be smaller than sizeof(void*), for obvious
reasons, and
bigger if it includes cached information (e.g. might include the vtable
pointer)
The only requirement is that reinterpret_cast<> works as specified.
HTH,
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: wade@stoner.com
Date: Wed, 26 Jul 2006 09:34:15 CST Raw View
skaller wrote:
> All data pointers have
> the same size, namely:
>
> sizeof(void*)
Chapter and verse? Or is this a proposal?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Wed, 26 Jul 2006 13:11:19 CST Raw View
Frederick Gotham wrote:
.
> However, the Standard provides no guarantee whatsoever that the following
> expression evaluates to "true":
>
> sizeof(char*) == sizeof(short*) == sizeof(int*) == sizeof(long*)
> == sizeof(float*) == sizeof(double long*) == sizeof(std::string*)
It is indeed not guaranteed by the standard, but I don't think that's
what you intended to say. :-) It would be legal for that expression to
evaluate to 'true', but extremely unlikely.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 27 Jul 2006 14:25:33 GMT Raw View
In article <1153913975.629368.85290@h48g2000cwc.googlegroups.com>,
Michiel.Salters@tomtom.com writes
>AFAIK, sizeof(T*) may be smaller than sizeof(void*), for obvious
>reasons, and
>bigger if it includes cached information (e.g. might include the vtable
>pointer)
>The only requirement is that reinterpret_cast<> works as specified.
Well static_cast should work as well.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: bop@gmb.dk ("Bo Persson")
Date: Mon, 24 Jul 2006 16:02:29 GMT Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> skrev i meddelandet
news:Rx4xg.11814$j7.320245@news.indigo.ie...
>
>
> I have a proposal, and it's to do with the inverse of the above:
>
> Where you have a POD struct which consists of one sole member
> object,
> the POD struct shall have the exact same size and alignment as the
> object
> on its own. This would allow for optimisations, such as copying an
> array:
>
> template<class T>
> struct SoleMember {
> T obj;
> };
>
> int main()
> {
> double buf1[256] = { /* ... */ };
> double buf2[256] = { /* ... */ };
>
> reinterpret_cast<SoleMember<double[256]>&>(buf1)
> = reinterpret_cast<SoleMember<double[256]>const&>(buf2);
> }
>
Why don't you try the much shorter code
std::copy(buf2, buf2 + 256, buf1);
and then complain to the supplier if your implementation doesn't
optimize the copying?
It is much easier to add specializations to the library (if needed)
than to change the language.
Bo Persson
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Tue, 25 Jul 2006 04:22:44 GMT Raw View
"Alf P. Steinbach" posted:
> ENIAC chatters its relays and says no.
Could you please run that past me one more time, in a language I understand?
:)
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Tue, 25 Jul 2006 04:22:29 GMT Raw View
Frederick Gotham posted:
> Where you have a POD struct which consists of one sole member object,
> the POD struct shall have the exact same size and alignment as the object
> on its own.
In fact, I would like it to hold true for non-POD's also:
templat <>
struct SoleMember<std::string> {
std::string obj;
};
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: alfps@start.no ("Alf P. Steinbach")
Date: Tue, 25 Jul 2006 05:32:00 GMT Raw View
* Frederick Gotham:
> "Alf P. Steinbach" posted:
>
>> ENIAC chatters its relays and says no.
>
>
> Could you please run that past me one more time, in a language I understand?
>
> :)
>
We're talking (mostly) about support for old, anachronistic computer
architectures, where e.g. a pointer to byte might be larger than a
pointer to class type object.
But I mixed up my references; it's been a long time! ENIAC was the
first electronic US computer, three years after the British Colossus,
and ten years after the German Z-series (but they were toys). What I
had in mind was really the Harvard Mark I, a relay-based very impressive
beastie which filled a huge room, was streamlined in glass and stainless
steel, and staffed and run by Navy engineers marching back & forth
"appearing to operate the thing while at attention" (according to a
Harvard scientist). You could hear the relays churning away, "like
listening to a roomful of old ladies knitting away with steel needles".
I don't think a C++ compiler was ever produced for this machine.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: jackklein@spamcop.net (Jack Klein)
Date: Tue, 25 Jul 2006 14:31:35 GMT Raw View
On Mon, 24 Jul 2006 14:24:00 GMT, fgothamNO@SPAM.com (Frederick
Gotham) wrote in comp.std.c++:
>
> The Standard guarantees that a pointer to a POD struct can be cast to a
> pointer to the type of its first element. Thus, the following is perfectly
> OK:
>
> struct Arb {
> double a;
> char b;
> void *p;
> };
>
> int main()
> {
> Arb obj;
>
> reinterpret_cast<double&>(obj) = 45.32;
> }
>
> (See 5.2.10/10 for my use of reinterpret_cast)
>
>
> I have a proposal, and it's to do with the inverse of the above:
>
> Where you have a POD struct which consists of one sole member object,
> the POD struct shall have the exact same size and alignment as the object
> on its own. This would allow for optimisations, such as copying an array:
>
> template<class T>
> struct SoleMember {
> T obj;
> };
>
> int main()
> {
> double buf1[256] = { /* ... */ };
> double buf2[256] = { /* ... */ };
>
> reinterpret_cast<SoleMember<double[256]>&>(buf1)
> = reinterpret_cast<SoleMember<double[256]>const&>(buf2);
> }
I agree with Alf's comments about alignment. Consider actual common
implementations, those which actually support the Intel hardware FPU
extended precision 80-bit floating point type as long double.
Microsoft and some others do not, Borland and gcc do on Windows.
On Borland's Win32 compilers, sizeof(long double) is 10 (8-bit bytes).
On gcc versions for Windows where I have tried it, sizeof(long double)
is 12, with the final two bytes set to all bits 0 on initialized
definitions.
The two compilers have made different decisions for trading off space
in arrays for access time in arrays.
Both implementations in general align struct/class types on 4-byte
boundaries.
If we require Borland to make a POD struct containing only a long
double exactly equal to a plain long double in size and alignment,
they have one of two choices: either increase the size of long double
by adding two padding bytes, as gcc does, or abandon their alignment
of all struct/class types to 4-byte boundaries.
This puts the ball back in your court. Your suggestion deprives
implementer of flexibility in making implementation decisions that
they have had for well over 30 years (including C), to eliminate a
possible implementation-defined side effect (padding), that C and C++
programmers have been successfully dealing with for that time.
Realize that the one of the reasons for the existing guarantees for
POD structs, namely the pointer conversion you mention and the
guarantee that the addresses of the members are in ascending order
relative to their order in the POD struct definition, is for
compatibility with C. Such a change would well break compatibility
with the same type used in a C program, unless you managed to persuade
the C standard committee to make the same change at the same time.
This is extremely unlikely.
Remember, too, that POD data type compatibility with C is in general
absolutely necessary for easy interface with third party libraries and
OS APIs, which almost universally directly accept C data types.
I do not know whether your proposal is based on some actual perceived
efficiency advantage, or merely for esthetics. But I do believe that
for such a major change in the language which might have far reaching
consequences, you would need to demonstrate that a significant
percentage of applications would realize a significant improvement.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Mon, 24 Jul 2006 14:24:00 GMT Raw View
The Standard guarantees that a pointer to a POD struct can be cast to a
pointer to the type of its first element. Thus, the following is perfectly
OK:
struct Arb {
double a;
char b;
void *p;
};
int main()
{
Arb obj;
reinterpret_cast<double&>(obj) = 45.32;
}
(See 5.2.10/10 for my use of reinterpret_cast)
I have a proposal, and it's to do with the inverse of the above:
Where you have a POD struct which consists of one sole member object,
the POD struct shall have the exact same size and alignment as the object
on its own. This would allow for optimisations, such as copying an array:
template<class T>
struct SoleMember {
T obj;
};
int main()
{
double buf1[256] = { /* ... */ };
double buf2[256] = { /* ... */ };
reinterpret_cast<SoleMember<double[256]>&>(buf1)
= reinterpret_cast<SoleMember<double[256]>const&>(buf2);
}
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: alfps@start.no ("Alf P. Steinbach")
Date: Mon, 24 Jul 2006 14:36:53 GMT Raw View
* Frederick Gotham:
> The Standard guarantees that a pointer to a POD struct can be cast to a
> pointer to the type of its first element. Thus, the following is perfectly
> OK:
>
> struct Arb {
> double a;
> char b;
> void *p;
> };
>
> int main()
> {
> Arb obj;
>
> reinterpret_cast<double&>(obj) = 45.32;
> }
>
> (See 5.2.10/10 for my use of reinterpret_cast)
>
>
> I have a proposal, and it's to do with the inverse of the above:
>
> Where you have a POD struct which consists of one sole member object,
> the POD struct shall have the exact same size and alignment as the object
> on its own. This would allow for optimisations, such as copying an array:
>
> template<class T>
> struct SoleMember {
> T obj;
> };
>
> int main()
> {
> double buf1[256] = { /* ... */ };
> double buf2[256] = { /* ... */ };
>
> reinterpret_cast<SoleMember<double[256]>&>(buf1)
> = reinterpret_cast<SoleMember<double[256]>const&>(buf2);
> }
It would require same pointer size for class type objects as for other
objects. Because you can declare and use a pointer to an incomplete
class type object, which might then turn out to have the same size and
alignment as e.g. a single char. ENIAC chatters its relays and says no.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]