 |
 |
|
 |
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
By my reading, neither C nor C++ guarantee the following:
union {
long x;
char* y;
} xyz;
xyz.y = NULL;
printf("%ld\n", xyz.x);
Neither C nor C++ guarantees that'll be zero (assuming
sizeof(char*)==sizeof(long)). In other words, neither guarantees that the
bit pattern in memory for NULL is actually all zeros, right?
So using memset() to clear a structure to 0 that contains pointers isn't
guaranteed to be portable to something like the AT&T 3B2, where NULL != 0x0
in memory?
I looked, but all I found were references to "null pointer value", and not
any bit patterns.
--
Darren New, San Diego CA, USA (PST)
"We'd like you to back-port all the changes in 2.0
back to version 1.0."
"We've done that already. We call it 2.0."
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le 30/07/2009 22:14, Darren New nous fit lire :
> By my reading, neither C nor C++ guarantee the following:
>
> union {
> long x;
> char* y;
> } xyz;
> xyz.y = NULL;
> printf("%ld\n", xyz.x);
>
> Neither C nor C++ guarantees that'll be zero (assuming
> sizeof(char*)==sizeof(long)). In other words, neither guarantees that
> the bit pattern in memory for NULL is actually all zeros, right?
>
> So using memset() to clear a structure to 0 that contains pointers isn't
> guaranteed to be portable to something like the AT&T 3B2, where NULL !=
> 0x0 in memory?
Well, it will be portable. memset() will work.
But if later you expect to check the pointer against NULL, you will be disappointed.
That's also why modern compiler can issue warning about usage of potentialy
uninitialised
variables.
In C++, you could make a class for your structure, and have a nice constructor to set
NULL in y; But that might somehow conflict with the usage of the union...
Is it really worth having an union there ? How do you, within the limit of strong
typing,
expect the union to behave ?
Only "legit" union I can know are sock_addr fields, allowing access to
8/16/32-bits-word
arrays.
Mixing a value and a pointer is a non-sense, unless you provide a real & sensible
usage.
>
> I looked, but all I found were references to "null pointer value", and
> not any bit patterns.
>
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le_Forgeron wrote:
> Well, it will be portable. memset() will work.
> But if later you expect to check the pointer against NULL, you will be disappointed.
Well, yes, that's what I was asking.
> In C++, you could make a class for your structure, and have a nice constructor to
set
> NULL in y; But that might somehow conflict with the usage of the union...
The union was just an unambiguous demonstration of what I meant by "the bit
pattern of a NULL pointer in memory." It's not actual code.
> Mixing a value and a pointer is a non-sense, unless you provide a real & sensible
usage.
memset() was more what I was talking about, which clearly mixes pointers and
values if you apply it to a structure with pointers in it.
--
Darren New, San Diego CA, USA (PST)
"We'd like you to back-port all the changes in 2.0
back to version 1.0."
"We've done that already. We call it 2.0."
Post a reply to this message
|
 |
|  |
|  |
|
 |
From: Fredrik Eriksson
Subject: Re: Quick C language-lawyer question...
Date: 30 Jul 2009 16:39:33
Message: <op.uxweb7gw7bxctx@e6600>
|
|
 |
|  |
|  |
|
 |
On Thu, 30 Jul 2009 22:14:16 +0200, Darren New <dne### [at] san rr com> wrote:
> In other words, neither guarantees that the bit pattern in memory for
> NULL is actually all zeros, right?
Right.
> So using memset() to clear a structure to 0 that contains pointers isn't
> guaranteed to be portable to something like the AT&T 3B2, where NULL !=
> 0x0 in memory?
Assuming that you want the pointers to have null pointer values, it is
only portable to architectures that explicitly specify an all-zero bit
pattern for null pointers.
> I looked, but all I found were references to "null pointer value", and
> not any bit patterns.
The standard does not specify any particular bit pattern, so naturally
there is no mention of such things.
--
FE
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
> On Thu, 30 Jul 2009 22:14:16 +0200, Darren New <dne### [at] san rr com> wrote:
> > In other words, neither guarantees that the bit pattern in memory for
> > NULL is actually all zeros, right?
> Right.
OTOH, how many modern architectures have null pointers which are not
all-zeros?
If you are writing C which must be portable to obscure embedded systems,
microwave ovens, 30-years-old obsolete mainframes and such, then you will
have to take that and a whole lot of other things into account. OTOH, if
you are just writing C for the PC, Mac and a few Unix computers out there,
the rules can often be relaxed a bit.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Darren New <dne### [at] san rr com> wrote:
> By my reading, neither C nor C++ guarantee the following:
>
> union {
> long x;
> char* y;
> } xyz;
> xyz.y = NULL;
> printf("%ld\n", xyz.x);
>
> Neither C nor C++ guarantees that'll be zero (assuming
> sizeof(char*)==sizeof(long)). In other words, neither guarantees that the
> bit pattern in memory for NULL is actually all zeros, right?
Absolutely right. Although it is common on most architectures to use an all-zero
value to represent a null pointer value, the specification only requires that
the binary representation is not used for any other purposes.
Just as you cannot rely on the char type to be an 8-bit integer. Or pointers to
be of the same size as long int, for that matter.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Warp wrote:
> OTOH, how many modern architectures have null pointers which are not
> all-zeros?
Now, me, being cynical, would say it's more "how many broken programs caused
enough trouble that future architectures made sure that 0 is the bit pattern
for null pointers?" :-) I was using a AT&T 3B2 in the early 90's that had
non-zero null pointers, but I think that's the only machine I ever used that
supported C that didn't use 0. Given they were insurance company computers,
I wouldn't be surprised if they're still around. Legacy business systems
have a way of living on for much longer than you'd think.
> you are just writing C for the PC, Mac and a few Unix computers out there,
> the rules can often be relaxed a bit.
Sure. It's language lawyering, not practical development. That's why I
called it that. :-)
On the other hand, I wonder if segmented pointers (as in near and far
pointers) used a segment of 0 to mean null for far pointers, or guaranteed
that CS:0 and DS:0 (or whtever) would map to invalid pages. Hmmm...
--
Darren New, San Diego CA, USA (PST)
"We'd like you to back-port all the changes in 2.0
back to version 1.0."
"We've done that already. We call it 2.0."
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Darren New <dne### [at] san rr com> wrote:
> > you are just writing C for the PC, Mac and a few Unix computers out there,
> > the rules can often be relaxed a bit.
> Sure. It's language lawyering, not practical development. That's why I
> called it that. :-)
Some would also say that if you have to worry about the bit-pattern of
null pointers, that's questionable optimization.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
clipka <nomail@nomail> wrote:
> Just as you cannot rely on the char type to be an 8-bit integer. Or pointers to
> be of the same size as long int, for that matter.
Or all pointers having the same size. (For example, in C++ member function
pointers will typically be larger than a void*. This surprises even many
experienced C++ programmers.)
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Warp wrote:
> Some would also say that if you have to worry about the bit-pattern of
> null pointers, that's questionable optimization.
The only reason I brought it up is this grody code I'm trying to make work
has a number of places where it initializes a structure to zero with
memset(), and the structure has pointers in it.
Given that the structure is a description of the hardware built into the
machine, it's not going to be portable to different CPUs anyway, but I just
got curious as to whether I'd misunderstood last time I looked thru the
specs. People often mistakenly argue that C++ guarantees the bit pattern is
zero because you now write { char* x = 0; } instead of { char* x = NULL; }
--
Darren New, San Diego CA, USA (PST)
"We'd like you to back-port all the changes in 2.0
back to version 1.0."
"We've done that already. We call it 2.0."
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Warp wrote:
> clipka <nomail@nomail> wrote:
>> Just as you cannot rely on the char type to be an 8-bit integer. Or pointers to
>> be of the same size as long int, for that matter.
>
> Or all pointers having the same size.
Well, that's been the case for different memory areas for a long time. Near
vs far pointers, at least. I guess folks don't remember way back in the bad
old days of x86 any more. :-)
--
Darren New, San Diego CA, USA (PST)
"We'd like you to back-port all the changes in 2.0
back to version 1.0."
"We've done that already. We call it 2.0."
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Warp <war### [at] tag povray org> wrote:
> If you are writing C which must be portable to obscure embedded systems,
> microwave ovens, 30-years-old obsolete mainframes and such, then you will
> have to take that and a whole lot of other things into account. OTOH, if
> you are just writing C for the PC, Mac and a few Unix computers out there,
> the rules can often be relaxed a bit.
.... though you shouldn't without need, because future portability is a
portability issue that typically applies to all software.
You never know what future hardware architectures bring.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
I once bought Zortech C for the price of a new PC just because it promised
easy access to large memory chunks, so I could address the whole 16MB of
memory the PC had. A broken promise, btw...
Well, thoses were the times of Turbo C, Turbo Pascal, 20 MB harddisks and 1
MHz processors...
BTW: my first computer was a VIC with a whole 5 kB main memory. To draw
complex graphics (like a monochrome sine curve ;-) you had to fill the video
memory with a sequence of ASCII chars, map the dot-matrix for those chars
(8x16 dots) to memory, and then redefine the respective rectangular
dot-matrices so that a graphical output would happen. If you have done this,
everything windows throws at you is just a minor nuisance ;-)
"Darren New" <dne### [at] san rr com> schrieb im Newsbeitrag
news:4a7227fe$1@news.povray.org...
> Warp wrote:
>> clipka <nomail@nomail> wrote:
>>> Just as you cannot rely on the char type to be an 8-bit integer. Or
>>> pointers to
>>> be of the same size as long int, for that matter.
>>
>> Or all pointers having the same size.
>
> Well, that's been the case for different memory areas for a long time.
> Near vs far pointers, at least. I guess folks don't remember way back in
> the bad old days of x86 any more. :-)
>
> --
> Darren New, San Diego CA, USA (PST)
> "We'd like you to back-port all the changes in 2.0
> back to version 1.0."
> "We've done that already. We call it 2.0."
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Darren New <dne### [at] san rr com> wrote:
> People often mistakenly argue that C++ guarantees the bit pattern is
> zero because you now write { char* x = 0; } instead of { char* x = NULL; }
BTW, those are perfectly identical according to the C99 spec: NULL *is* either
defined as the numeric literal 0, or the very same cast to void*.
People forget though that char* x = 0 actually involves an implicit typecast -
just like they forget (or never learn in the first place) that a typecast in C
does *not* necessarily preserve the binary representation...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
"TC" <do-not-reply@i-do get-enough-spam-already-2498.com> wrote:
> BTW: my first computer was a VIC with a whole 5 kB main memory. To draw
> complex graphics (like a monochrome sine curve ;-) you had to fill the video
> memory with a sequence of ASCII chars, map the dot-matrix for those chars
> (8x16 dots) to memory, and then redefine the respective rectangular
> dot-matrices so that a graphical output would happen. If you have done this,
> everything windows throws at you is just a minor nuisance ;-)
Heh - the Amstrad CPC featured dedicated 16kB of pure-graphics display memory;
however, due to (mis-)using a display controller originally designed for text
operation, it wasn't too straightforward either:
- a raster line would be comprised of 80 bytes
- a batch of consecutive raster lines would have an address offset of 2048 to
each other
- each batch of lines would have an address offset of 80 bytes to one another
And if you forgot to clear the screen before directly accessing the display
memory, the start address might have been anywhere, due to the hardware
scrolling capabilities of the display controller...
(Double-buffering was nice though: The display controller could access any of
the four 16kB banks of RAM; bank 1 and 3 were of no use as the firmware used
parts for special purposes, but bank 4 was dedicated to the display, and with a
small enough program bank 2 could serve as a second frame buffer.)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
clipka wrote:
> Darren New <dne### [at] san rr com> wrote:
>> People often mistakenly argue that C++ guarantees the bit pattern is
>> zero because you now write { char* x = 0; } instead of { char* x = NULL; }
>
> BTW, those are perfectly identical according to the C99 spec: NULL *is* either
> defined as the numeric literal 0, or the very same cast to void*.
I know that. I was under the impression that C++ got rid of the possibility
of it being a cast, and strongly suggested people just use the literal 0.
> People forget though that char* x = 0 actually involves an implicit typecast -
> just like they forget (or never learn in the first place) that a typecast in C
> does *not* necessarily preserve the binary representation...
Yes. Well of course { float f = 2; } involves a change in the
representation. A lot of people also forget that pointers to functions have
different rules from pointers to data (like, you can't cast them to void*
reliably).
--
Darren New, San Diego CA, USA (PST)
"We'd like you to back-port all the changes in 2.0
back to version 1.0."
"We've done that already. We call it 2.0."
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
TC wrote:
> BTW: my first computer was a VIC with a whole 5 kB main memory. To draw
> complex graphics (like a monochrome sine curve ;-) you had to fill the
> video memory with a sequence of ASCII chars, map the dot-matrix for
> those chars (8x16 dots) to memory, and then redefine the respective
> rectangular dot-matrices so that a graphical output would happen. If you
> have done this, everything windows throws at you is just a minor
> nuisance ;-)
mmm. 8 bit computing ;)
A long time ago, I did some work with a Gamboy Color game, which aside
from the Z80 clone processor it was using was kind of similar to the
NES. There's a reason the backgrounds are tile-based on those consoles. ;)
I'm more familiar with how the NES graphics system worked, than I am the
GBC's graphics system (I had access to Nintendo's developer
documentation, the NES documentation fascinated me, since I (mis)spent a
lot of time playing NES games) essentially you had a character table
that had the sprites defined, each character comprised of four colors,
8x8 so, each scanline of the character was 16 bits wide. You defined
those characters, then referenced them in a table, along with some
flags, one of which was which of the 4 loaded palettes to use when
drawing that character on screen. The table was 2 screens, either
vertical or horizontal (and could be scrolled either way, there was also
a special trick to scroll both vertically and horizontally.) I want to
say there were 2 bytes per entry, one was the block, the other was the
flags. Sprites were also handled by the same character table/palette
system.
Wow... that was a huge digression.. ahem.. ;)
--
~Mike
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Darren New wrote:
> By my reading, neither C nor C++ guarantee the following:
>
> union {
> long x;
> char* y;
> } xyz;
> xyz.y = NULL;
> printf("%ld\n", xyz.x);
>
> Neither C nor C++ guarantees that'll be zero (assuming
> sizeof(char*)==sizeof(long)). In other words, neither guarantees that
> the bit pattern in memory for NULL is actually all zeros, right?
C/C++ unions are intended for allowing one piece of memory to store
different types. It has been used as a conversion mechanism by
enterprising coders, but this requires excellent knowledge of the
implementation of each type in the union. Consequently code like this
cannot be guaranteed portable.
Furthermore, NULL is a pre-processor #define, and thus is also
implementation-specific. Sure, NULL is defined as 0 on every platform
for which I've ever coded (so that I often type "0" when I'm supposed to
type "NULL") but I'm sure that an exception can be found at places like
www.thedailywtf.com .
Regards,
John
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|
 |