"a < b < c" not the same as "(a < b) && (b < c)"?

N

Netocrat

Netocrat said:
[W]hy would you would write the boolean value [of a pointer] to
a variable[?]

Here's a contrived snippet (not compilable or verified correct):

Thank you for your help.
#include <stdbool.h>

_Bool demofunc(char **argv) /* final member of argv array is NULL */
{
_Bool ret;
char **argp = argv;

/* do something with argp */
...

/* store whether argp ended on final array member */
ret = argp;


/* reset argp and do something else with it */
argp = argv;
...

return ret; /* or otherwise utilise the value of ret */
}

Why? "utilize the value of ret" how?

Read the code, use your imagination and [insert appropriate Zen saying of
your preference].
By your own code, argp is now pointing somewhere else.

Right - that's the whole point - you wanted a situation where one couldn't
simply use the value of the pointer. This is such a situation: the
pointer's value is now different so we can't use it anymore.
ret is merely providing the information that
a pointer once pointed to something,

More importantly, it indicates whether the initial processing block
reached the end of the array (false) or not (true).

[...]
 
M

Michael Mair

Mabden said:
[W]hy would you would write the boolean value [of a pointer] to
a variable[?]

Here's a contrived snippet (not compilable or verified correct):


Thank you for your help.

#include <stdbool.h>

_Bool demofunc(char **argv) /* final member of argv array is NULL */
{
_Bool ret;
char **argp = argv;

/* do something with argp */
...

/* store whether argp ended on final array member */
ret = argp;


/* reset argp and do something else with it */
argp = argv;
...

return ret; /* or otherwise utilise the value of ret */
}


Why? "utilize the value of ret" how? By your own code, argp is now
pointing somewhere else. ret is merely providing the information that a
pointer once pointed to something, without the pointer itself or any tie
to the pointer to say whether it is still pointing to anything, and, if
it is an INVALID, UNITITIALIZED pointer - it's probably still going to
be "true" except on SOME machines or compilers where it may NOT be true.
Sometimes. And global pointer may have differences than automatic
variables (in functions).

Didn't you see my example:

_Bool EndOfString (char *p)
{
_Bool bpVal=false;

while (*p != '\0')
bpVal = p++; /* flag if p becomes null?! WTF? */

return bpVal; /* return "the end of the string was once pointed to" flag
*/
}

I'm not saying code can't be written. I just can't see why anyone would.
Why not pass around the actual pointer.

What value does this actually have in Real Life?!!! Has ANYONE even /
ever done this?? Can you think of ANY reason to do this that wouldn't be
a Bad Idea?!

_Bool success = true;

success = isBla(.....) && success;
success = isBlub(....) && success;
pFoo = getFoo();
if (success = pFoo && success)
{
....
}
.....
return success;

for your arbitrary company's SESE policy. Or whatever.


Cheers
Michael
 
M

Mabden

Michael Mair said:
_Bool success = true;

success = isBla(.....) && success;
success = isBlub(....) && success;
pFoo = getFoo();
if (success = pFoo && success)
{
....
}
....
return success;

for your arbitrary company's SESE policy. Or whatever.

OK, good answer Michael. Thank you for understanding my question.

At first glance I thought you had missed the point (so to speak), as I
thought the = in the if() was a typo. The code doesn't look like
"natural C" to me, however, and I doubt I would code it that way. Plus,
the compiler is going to scold you. ;-)

Note that your "success" is determined by pFoo not being equal to null.

I still have a question as to whether an automatic pointer (in a
function, initialized by the compiler) is set to all-bits-zero or to the
address of NULL (void *(0)). If pointers are init'ed to zero as other
automatic variables are in a function, and NULL points to somewhere else
in memory aren't they different?

I'm going to give an example as I keep getting "answers" that miss the
point, so sorry if you understand and this bores you - it bores me more
to try to explain my point a thousand times over, but here goes:

NULL is a pointer to a zero in memory at 0x11112222.
My function has a pointer that gets initialized automagically. I don't
know whether it gets init'ed to NULL (0x11112222) or all-zeros
(0x00000000). What does The Standard say?

Now, if the automatic pointer is actually init'ed to NULL, then there is
no problem that I can see.

IFF it is the second case of 0x00000000, then it seems to me that
0x00000000 != 0x11112222. Does that seem reasonable? In this case,
assigning the 0x00000000 to a _Bool would seem, to me, to produce a
false since it is not NULL. This is what I was saying to Flash that
turned into a lecture about NULL not being all-zeros (which is the point
I was actually making).

If they are different, and your getFoo() returns a pointer that is not
NULL, but is all-bits-zero then wouldn't storing that pointer in a _Bool
variable give a false value? I believe it should, since 0x00000000 !=
0x11112222, and 0x00000000 may be a valid address in this memory space
on some hardware / software combo.

However, if you used the actual pointer you would write code like this:

pFoo = getFoo();
if (pFoo && success)
{
/* actually do something with pFoo, since you went and got it... */
return true; /* or return success; */
}
else return false;

Now my understanding is that the if() would work in both cases of pFoo
being NULL or pFoo being all-zeros, is that correct? If so, then using a
boolean variable to store the value of a pointer would seem like a Bad
Idea.

Am I the only one not understanding this?

p.s. I'm not familiar with the term SESE, and neither is my acronym
dictionary at
http://www.ucc.ie/cgi-bin/uncgi/acronym
What does it mean, and does anyone have a better acronym dictionary?

p.p.s. Please, please, please don't reply that NULL does not have to be
all-zeros...
 
N

Netocrat

I still have a question as to whether an automatic pointer (in a
function, initialized by the compiler) is set to all-bits-zero or to the
address of NULL (void *(0)).

Neither - automatic variables are not initialised by the compiler. But
when a static global pointer variable is initialised, the compiler sets it
to NULL, not all-bits-zero (unless that also happens to be the
representation of NULL).

Better than referring to NULL as an "address" (it doesn't actually refer
to any valid memory location) is to term it a "representation".

[...]
NULL is a pointer to a zero in memory at 0x11112222. My function has a
pointer that gets initialized automagically. I don't know whether it
gets init'ed to NULL (0x11112222) or all-zeros (0x00000000). What does
The Standard say?

To repeat: NULL (0x11112222).

Minor quibble with your phrasing: "a pointer to a zero in memory at" would
be better written "represented by the bit-pattern of the number"
Now, if the automatic pointer is actually init'ed to NULL, then there is
no problem that I can see.

Good, that makes (at least) two of us.

[...]
 
P

Peter Nilsson

There's an entire chapter of the FAQ dedicated to this stuff people! ;)
Neither - automatic variables are not initialised by the compiler. But
when a static global pointer variable is initialised, the compiler sets
it to NULL,

The initial value of an uninitialised static duration pointer is a null
pointer.
not all-bits-zero (unless that also happens to be the
representation of NULL).

NULL does not have a representation, it's a macro which expands to an
implementation defined null pointer constant. It may even expand to
something like __null.
Better than referring to NULL as an "address" (it doesn't actually refer
to any valid memory location) is to term it a "representation".

IMO, it's better to talk about null pointers and null pointer
constants.
NULL and 0 (et al) are syntactic symbolism.

But, when talking about null pointers, it's worth remembering that
there
may be more than one representation, although they will compare equal.
 
N

Netocrat

Netocrat wrote:

IMO, it's better to talk about null pointers and null pointer constants.
NULL and 0 (et al) are syntactic symbolism.

Yes, that's even better.
But, when talking about null pointers, it's worth remembering that there
may be more than one representation, although they will compare equal.

Point taken.
 
R

Richard Bos

As for the latter: said:
Single entry, single exit,

This is correct, but...
thus a Boolean to capture the success.

....this doesn't follow. The single exit can easily be an int, or a
pointer. Or even a struct, though that is, of course, cheating. WHat
Mabden described is even more strict than a normal SESE policy.

Richard
 
M

Mabden

Netocrat said:
Yes, that's even better.
equal.

Point taken.

OMFG! I can't believe you guys. In post post script I specifically asked
not to go there.

"p.p.s. Please, please, please don't reply that NULL does not have to be
all-zeros..."

I am NOT talking about NULL, where NULL resides, or any other topic
about NULL or null or _null or anything like that. Did you look at the
code - no references to null.

One question is what are automatic variables in a function (not static)
initialized to according to the Standard?

Nothing there about global variables. Nothing about static variables.

I'm asking the hard questions. Sorry, kiddies.
 
M

Mabden

Richard Bos said:
dictionary?


Noted.

This is correct, but...


...this doesn't follow. The single exit can easily be an int, or a
pointer. Or even a struct, though that is, of course, cheating. WHat
Mabden described is even more strict than a normal SESE policy.

I studied Meyers and such when we coded badly. You HAD to make some
rules! SESE was a first step to stem the tide. Later, languages that
didn't use goto's were invented and functions were created. At that
point it became obvious that it was OK to leave a function from many
points. The problem was jumping in to the middle. SESE was about gotos.
And the code that was posted to show my why we would use booleans to
store pointers was about as old of an idea. I guess that's why it looked
both familiar, and wrong.

Jumping into and out of "functions" or "subroutines". Nah - they were
just lines of code. People went mad! Mad, I tell you! I was pure chaos.
We did things to code you can't imagine - overlaying code with data
because a bit -ONE BIT - was flipped! This memory means this, unless
this bit is on then it is an entirely different record. But check this
other bit to see of it is data or a new subroutine. If it is a new
subroutine, check byte 7-14 for the offset of the start of the
subroutine. Oh, and make sure you put back the original data when you
are done. Can you say "cleanup on aisle 3!"?

Ahhhh... the good old days. We burned with the FIRE in those days.
Compiles took HOURS, my friend - you THOUGHT about what you wrote!
Chaos! Core dumps! Ties! Madness, I tell you!

I cannot speak any more... the madness comes, it comes!!!
 
N

Netocrat

OMFG! I can't believe you guys. In post post script I specifically asked
not to go there.

"p.p.s. Please, please, please don't reply that NULL does not have to be
all-zeros..."

There are other readers of the newsgroup than yourself. Your use of
terminology was poor and deserved correction. Peter was right to improve
my correction.

In any case where do you see the statement in your p.p.s made? (it
isn't).

[...]
One question is what are automatic variables in a function (not static)
initialized to according to the Standard?

Which I answered:
"...automatic variables are not initialised by the compiler."

That could be worded better: according to the Standard, the initial value
of an automatic variable is indeterminate.

[...]
I'm asking the hard questions. Sorry, kiddies.

You're asking the FAQs. Read the relevant section first if you intend to
post again.
 
K

Keith Thompson

Mabden said:
One question is what are automatic variables in a function (not static)
initialized to according to the Standard?

They aren't implicitly initialized to anything.

Have you considered getting a copy of the standard? Or at least a
draft (Google "n1124.pdf")?
 
M

Mabden

Keith Thompson said:
They aren't implicitly initialized to anything.

I'm going to take that as including pointers. Please tell me if pointers
are a specific case.

I thought they are zeroed. Is it globals that are zeroed? I always
initialize anything I use, so I never really think about it.

OK, but you are making my point. The pointer is uninitialized. It
contains random bits. It may contain all-zeros for all we know. There is
no way to know. Hence random. Assign it to a _Bool and you don't know
what it will be.
Have you considered getting a copy of the standard? Or at least a
draft (Google "n1124.pdf")?

Nope. My code works great, thanks. I just "do it right" and I don't have
trouble with issues that are Standard minutia. In my view, when your
code falls into the realm of something Madben is talking about on c.l.c,
then you are a barbarian. ;-0
 
M

Michael Mair

Richard said:
This is correct, but...


...this doesn't follow. The single exit can easily be an int, or a
pointer. Or even a struct, though that is, of course, cheating. WHat
Mabden described is even more strict than a normal SESE policy.

Sorry, I did not quote enough context as I was in a hurry :-/
I meant this in the context of the, alas, unquoted example.

Cheers
Michael
 
S

Steve Summit

Mabden said:
K>>> I was about to disagree. Fortunately, I looked it up first; you
K>>> can assign a pointer value directly to a _Bool. Interesting.

M>> What does that mean? Assign the pointer to a _Bool or the value
M>> pointed at to a _Bool? The former seems nonsensical,

The rest was snipped, but I think you get my question. I am asking why
people would be recording the TRUE and FALSE values somewhere and using
them somehow...

You're right, they probably wouldn't be. The assignment
arguably *doesn't* make much sense. The Standard gives it a
meaning, and it's the correct meaning under the circumstances,
but if you don't like it, don't use it.
The standard you linked to just talks about checking whether a pointer
is NULL or not.

Correct. That's just about the only clear-cut, unambiguous
distinction there is.
Again, why would you assign a pointer address to a _Bool variable,
and if you did wouldn't that result change depending on the hardware /
software platform?

No, the result would not change.
You seem to be saying (but don't actually say) that the _Bool
variable will be TRUE for any valid pointer, well no you don't say
valid.

Right. Key distinction.
You seem to be saying that if the pointer is set to NULL then my
variable, say Bpval, will be false.
Right.

If my pointer is initialized, then Bpval will be true.

Right again.
You also say that these values will be consistant across any Standard
C implementation, and it doesn't matter where NULL is (all zeroes,
some special hardware address, a random point in memory, etc.)

Right, right, right.
You don't address the case of a pointer that has not been initialized
yet,

That's the tricky case.

At the level we're talking about here, there are really three
kinds of pointer values:

0. Null (and hence invalid) pointers.
1a. Non-null, initialized, valid pointers.
1b. Non-null invalid pointers.

All null pointers are invalid, but not all non-null pointers are
valid. If a pointer is null, it is guaranteed to be invalid, but
if a pointer is non-null, you can't always be sure that it's
valid. The conditionals

if(p != NULL)

and the "shorthand"

if(p)

test merely for non-null pointers; they do *not* necessarily test
for valid pointers.

Here is a code fragment illustrating the three cases:

int i = 0;
int *ip0 = NULL;
int *ip1a = &i;
int *ip1b = (int *)0xdeadbeef;

printf("ip0 is %sNULL\n", ip0 != NULL ? "non-" : "");
printf("ip1a is %sNULL\n", ip1a != NULL ? "non-" : "");
printf("ip1b is %sNULL\n", ip1b != NULL ? "non-" : "");

Both ip1a and ip1b are non-NULL. If you inspect the value of
*ip1a or try to set it to something else:

*ip1b = 42;

it will work. If you try to do anything with *ip0 or *ip1b it
will almost certainly fail.
and I suppose it might depend on whether it is a global or an
automatic variable. I'm assuming an automatic variable that is
a pointer is init'ed to all-zeros by the compiler, like all the
other automatic variables - what does the Standard say about that?

Well, for one thing, it's the other way around. "Global"
(really, static-duration) variables are automatically initialized
to 0, which is to say, as if the programmer had written something
like "= 0". So global pointer variables are guaranteed to start
out as null pointers. It's the automatic variables which, if the
programmer doesn't explicitly initialize them, contain garbage.

Has anyone pointed you at the comp.lang.c FAQ list yet?
It covers a lot of this.

It's useful to adopt a programming style in which "case 1b" never
occurs. If you always initialize pointers to NULL or to the
address of some valid storage (perhaps by calling malloc), and if
you always set pointers to NULL when they become invalid (such as
when you call free), then, by convention, you *can* use

if(p != NULL)

to test for valid pointers. But the Standard C language doesn't
guarantee (by itself) that this will work; you need to augment
the Standard (so to speak) with your own programming standard if
you're going to get away with this.
BTW people, if you are going to tell someone to read the FAQ,

Ah. Someone did point it out.
please put a link in your post, every time. Please don't assume
the OP has the link handy on their desktop.

It really isn't that hard to find. For example, you can enter
"C FAQ" or "comp.lang.c FAQ" into google, press the "I'm Feeling
Lucky" button, et voilà, there you are.
 
R

Richard Heathfield

Steve Summit said:
It really isn't that hard to find. For example, you can enter
"C FAQ" or "comp.lang.c FAQ" into google, press the "I'm Feeling
Lucky" button, et voilà, there you are.

Steve - <http://www.eskimo.com/~scs/C-FAQ/top.html> is mildly out of date
compared to the ASCII version <ftp://ftp.eskimo.com/u/s/scs/C-faq/faq.gz> -
do you have any plans to copy the changes into the HTML version?

I am by no means the most dynamic of site updaters myself, so this is not a
nag, merely an enquiry!
 
S

Steve Summit

Mabden said:
in message


I'm going to take that as including pointers.
Correct.

Please tell me if pointers are a specific case.

No, they are not a special case; they're not implicitly
initialized to anything, either.
I thought they are zeroed.

You thought wrong.
Is it globals that are zeroed?
Yes.

OK, but you are making my point. The pointer is uninitialized.
It contains random bits. It may contain all-zeros for all we know.
There is no way to know. Hence random. Assign it to a _Bool and
you don't know what it will be.

The way to think about pointer-assigned-to-bool, I think, is that
for any expression e, of any type, the assignment

bool b;
b = e;

gets you, in b, the same answer you would have gotten if you had
said

if(e) b = true; else b = false;

Now, it's true, if you compute this condition e, assign it to b,
and then look at b later -- that is, whenever you do something like

bool b = e;

/* ...then some other stuff happens... */

if(b)

the underlying condition might have changed out from under you
in the meantime. But that's true whether or not e involves a
pointer. The pointer might no longer be non-null, the file might
not still not exist, the pod bay doors might not still be open.
That's why "caching" a boolean (or any!) value in this way is
always at least somewhat risky, if not a downright bad idea.

But then again, of course, sometimes there's a good reason to do
it, and you usually can, if you're suitably careful.

If anyone is at all surprised by my transformation of

b = e;

into

if(e) b = true; else b = false;

, don't be. There's nothing magical here.
It's also equivalent to

b = (e ? true : false);

It's also equivalent to

b = (e != 0);

And, coming full circle, slapping "!= 0" next to an expression
is, in effect, what the compiler always does whenever you write

if(e)

That's why

if(ptr)

works, and why it's 100% functionally equivalent to

if(ptr != NULL)

, and why it's perfectly portable and reliable and safe to use,
no matter what the underlying representation of a null pointer is.
As the FAQ list points out, the correct interpretation of

if(ptr)
or
if(ptr != 0)

does not involve converting the pointer into an integer; it
involves converting the constant integer 0 into a null pointer
constant, and comparing against that.
 
K

kuyper

Mabden said:
....
I still have a question as to whether an automatic pointer (in a
function, initialized by the compiler) is set to all-bits-zero or to the
address of NULL (void *(0)). If pointers are init'ed to zero as other
automatic variables are in a function, and NULL points to somewhere else
in memory aren't they different?

Automatic pointers are uninitialized unless explicitly intitialized. If
explicitly initialized, they're initialized with whatever you specified
in the explicit initialization.

Therefore, I'm going to assume you're actually talking about static
pointers. If not explicitly initialized, they are zero-initialized,
which means that they are initialized with a value of 0 converted to
the appropriate pointer type. The result of that conversion is
guaranteed to be a null pointer; it's not guaranteed to have all bits
0, and it's not guaranteed to refer to the memory location with an
address of 0 (which are two seperate issues).
I'm going to give an example as I keep getting "answers" that miss the
point, so sorry if you understand and this bores you - it bores me more
to try to explain my point a thousand times over, but here goes:

NULL is a pointer to a zero in memory at 0x11112222.
My function has a pointer that gets initialized automagically. I don't
know whether it gets init'ed to NULL (0x11112222) or all-zeros
(0x00000000). What does The Standard say?

It gets intialized with a null pointer. If the implementation provides
multiple representations for null pointers of a given type (which it is
permitted to do), then that null pointer might or might not have the
same bit pattern it would have had if it had been initialized with
NULL. However, it is guaranteed to compare equal with NULL, regardless
of whether it has the same bit pattern, because all null pointers are
guaranteed to compare equal to each other.
Now, if the automatic pointer is actually init'ed to NULL, then there is
no problem that I can see.

NULL expands into a NULL pointer constant. The result of assigning a
null pointer constant to an object of pointer type is that the pointer
will contain a representation of a null pointer. However, if an
implementation allows multiple representations of a null pointer, it's
perfectly legal for assignment of NULL to a variable to produce a
different representation of a null pointer each time it occurs.
IFF it is the second case of 0x00000000, then it seems to me that
0x00000000 != 0x11112222. Does that seem reasonable?

0x00000000 != 0x11112222, regardless of which of those two cases apply.
That's simply a matter of ordinary arithmetic applied to hexadecimal
integer literals. However, if those integers represent memory
locations, there's no guarantee that they refer to different memory
locations. I've seen real machines where the same memory location had
multiple representations.

If an implementation chooses to define pointers referring to both of
those addresses as null pointers, then those pointers must compare
equal, regardless of which location they nominally point at.
Technically, it's not meaningful to talk about which location a null
pointer points at, because there's no way within strictly conforming C
to find out anything about that location. However, an implementation
can chooses to make the undefined behavior that results from
dereferencing a null pointer, be that it acts as a normal pointer
referencing a specific memory location. Therefore, there can be an
implementation-specific meaning to the concept of where an null pointer
points at; there just isn't any portable meaning to the concept.
... In this case,
assigning the 0x00000000 to a _Bool would seem, to me, to produce a
false since it is not NULL. This is what I was saying to Flash that
turned into a lecture about NULL not being all-zeros (which is the point
I was actually making).

Assigning a null pointer value to a _Bool always results in the _Bool
variable containing the value false, regardless of what bit pattern the
pointer value is represented by, and regardless of which address that
pointer value refers to.
If they are different, and your getFoo() returns a pointer that is not
NULL, but is all-bits-zero then wouldn't storing that pointer in a _Bool
variable give a false value?

The relevant question is whether the bit pattern represents a null
pointer. It doesn't matter whether it's all-bits-zero, it doesn't
matter whether it represents an address of 0, and it doesn't matter if
the value it was most recently initalized with or that was assigned to
it wasn't NULL. All that matters is whether the result of the most
recent initialization/assignment was a null pointer. If it was, then
the _Bool value will be "false", otherwise it's true.
I believe it should, since 0x00000000 !=
0x11112222, and 0x00000000 may be a valid address in this memory space
on some hardware / software combo.

If an implementation chooses to treat a pointer to the memory address
of 0x00000000 a null pointer, and to also treat a pointer to the memory
address 0x11112222 as a null pointer, those pointers must compare equal
to all null pointers, including each other. They must both compare
unequal to any pointer to an actual object, and must both covert to
"false" in a _Bool context. That means that the implementation is
required to ensure that any objects actually located at those addresses
cannot be referred to by a C program using strictly conforming code.
However, if you used the actual pointer you would write code like this:

pFoo = getFoo();
if (pFoo && success)
{
/* actually do something with pFoo, since you went and got it... */
return true; /* or return success; */
}
else return false;

Now my understanding is that the if() would work in both cases of pFoo
being NULL or pFoo being all-zeros, is that correct?

No, for the reasons given above.
p.p.s. Please, please, please don't reply that NULL does not have to be
all-zeros...

As far as I can tell, I avoided that.

I can back up almost every statement I made above with an explicit
citation from the C standard. Ordinarily, I would include those
citations in the text, but in this case there are just too many of
them. If you find any of my assertions controversial, tell me which
ones and I'll give you the relevant citations.

Note: I don't normally monitor comp.lang.c; I came here only to
back-track some comments you made on comp.std.c. I'll watch this thread
for a day or two, but if you take longer than that to respond to this
message, it would be helpful if you send me e-mail reminding me of your
response.
 
K

Keith Thompson

Mabden wrote: [...]
I still have a question as to whether an automatic pointer (in a
function, initialized by the compiler) is set to all-bits-zero or to the
address of NULL (void *(0)). If pointers are init'ed to zero as other
automatic variables are in a function, and NULL points to somewhere else
in memory aren't they different?

Automatic pointers are uninitialized unless explicitly intitialized. If
explicitly initialized, they're initialized with whatever you specified
in the explicit initialization.

Therefore, I'm going to assume you're actually talking about static
pointers. If not explicitly initialized, they are zero-initialized,
which means that they are initialized with a value of 0 converted to
the appropriate pointer type. The result of that conversion is
guaranteed to be a null pointer; it's not guaranteed to have all bits
0, and it's not guaranteed to refer to the memory location with an
address of 0 (which are two seperate issues).

I think he was actually asking about the implicit initialization of
automatic variables. The answer, of course, is that there is none.

[...]
NULL expands into a NULL pointer constant.

A very small quibble, you meant "null pointer constant", not "NULL
pointer constant". I'm sure that was just a typo.

[...]
The relevant question is whether the bit pattern represents a null
pointer. It doesn't matter whether it's all-bits-zero, it doesn't
matter whether it represents an address of 0, and it doesn't matter if
the value it was most recently initalized with or that was assigned to
it wasn't NULL. All that matters is whether the result of the most
recent initialization/assignment was a null pointer. If it was, then
the _Bool value will be "false", otherwise it's true.

To expand on that a little:

The current value of a pointer object is the value most recently
assigned to it, or the value with which it was initialized if it's
never been assigned to. (I'm assuming "assigned to" refers to any
method of modifying the value, including memcpy(); I'm also ignoring
any issues involving volatile objects.) The same is true of objects
of any type; there's nothing special about pointers here.

If the current value of a pointer object is a null pointer, assigning
it to a _Bool object assigns the value 0 (false). If the current
value is anything other than a null pointer, assigning it to a _Bool
object assigns the value 1 (true). If the pointer object is
uninitialized, which can happen if it's an automatic variable with no
explicit initialization, then any attempt to refer to its value
invokes undefined behavior; attempting to assign this uninitialized
value to a _Bool object can do anything. (It's likely to assign
either 0 or 1, but it could, for example, crash the program as soon as
the pointer value is accessed.) This can and should be avoided by
consistently initializing all variables (explicitly or implicitly)
before using them.
 
M

Mabden

Automatic pointers are uninitialized unless explicitly intitialized. If
explicitly initialized, they're initialized with whatever you specified
in the explicit initialization.

Therefore, I'm going to assume you're actually talking about static
pointers. If not explicitly initialized, they are zero-initialized,
which means that they are initialized with a value of 0 converted to
the appropriate pointer type. The result of that conversion is
guaranteed to be a null pointer; it's not guaranteed to have all bits
0, and it's not guaranteed to refer to the memory location with an
address of 0 (which are two seperate issues).

Yes, that is what I meant. If the pointer is set to a value. You use
static, someone else pointed out I had it backwards, and the it was
globals that are zeroed. The ones that are set to something
automatically; I wondered whether that something was all-zeros, or NULL.
Your answer, which I've snipped for brevity, was a null pointer.
NULL expands into a NULL pointer constant. The result of assigning a
null pointer constant to an object of pointer type is that the pointer
will contain a representation of a null pointer. However, if an
implementation allows multiple representations of a null pointer, it's
perfectly legal for assignment of NULL to a variable to produce a
different representation of a null pointer each time it occurs.

I didn't know that.
0x00000000 != 0x11112222, regardless of which of those two cases apply.
That's simply a matter of ordinary arithmetic applied to hexadecimal
integer literals. However, if those integers represent memory
locations, there's no guarantee that they refer to different memory
locations. I've seen real machines where the same memory location had
multiple representations.

If an implementation chooses to define pointers referring to both of
those addresses as null pointers, then those pointers must compare
equal, regardless of which location they nominally point at.
Technically, it's not meaningful to talk about which location a null
pointer points at, because there's no way within strictly conforming C
to find out anything about that location. However, an implementation
can chooses to make the undefined behavior that results from
dereferencing a null pointer, be that it acts as a normal pointer
referencing a specific memory location. Therefore, there can be an
implementation-specific meaning to the concept of where an null pointer
points at; there just isn't any portable meaning to the concept.
Hmmmm...

Assigning a null pointer value to a _Bool always results in the _Bool
variable containing the value false, regardless of what bit pattern the
pointer value is represented by, and regardless of which address that
pointer value refers to.

THAT was my question. I was asking if an all-bits-zero address that is
assigned to a _Bool, would essentially be a random operation, since some
machines may put NULL at all-bits-zero and some may not; maybe not so
much random, but a hiding bug. You are saying that that should not
happen.
The relevant question is whether the bit pattern represents a null
pointer. It doesn't matter whether it's all-bits-zero, it doesn't
matter whether it represents an address of 0, and it doesn't matter if
the value it was most recently initialized with or that was assigned to
it wasn't NULL. All that matters is whether the result of the most
recent initialization/assignment was a null pointer. If it was, then
the _Bool value will be "false", otherwise it's true.

Thank you. Problem solved. We can all move on now.
"Nothing to see here, folks, move along..."
As far as I can tell, I avoided that.

Thank VERY much for that. Nice job.
I can back up almost every statement I made above with an explicit
citation from the C standard. Ordinarily, I would include those
citations in the text, but in this case there are just too many of
them. If you find any of my assertions controversial, tell me which
ones and I'll give you the relevant citations.

You describe the problem I had, and your take on it is so thorough, I
can't bear to think you are mistaken.

Thank you for your time.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top