Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » textprintf with null string

Credits go to CGamesPlay, Evert, gillius, gnolam, Kitty Cat, Korval, Krzysztof Kluczek, Matthew Leverton, ReyBrujo, X-G, and Zaphos for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
textprintf with null string
Zaphos
Member #1,468
August 2001

Okay, I suppose, but it is special and is treated as such standardly by C library functions. Your argument seemed to imply that it wasn't special, or that it would be dangerous to treat it as such.

Anyway, I agree with the gist of your point. Especially in a library in which speed is important (and a gaming library certainly qualifies) it doesn't make sense to do special error checking for cases that the user shouldn't force on the lib in the first place.

X-G
Member #856
December 2000
avatar

Doesn't it say somewhere that NULL (which is a special value) might not actually be 0, but could be something else entirely?

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Zaphos
Member #1,468
August 2001

I think it's just 0 or (void*)0 ... the GNU C library manual says:
[url http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_28.html#SEC482]

I'm not sure where the official C standard might be found for free (the ANSI one costs money, anyway) so it's hard to verify that this is required in all compilers, but I do think it would be difficult to have a non-zero NULL that works (which is to say, evaluates to false and represents an unassigned pointer).

Evert
Member #794
November 2000
avatar

Quote:

Doesn't it say somewhere that NULL (which is a special value) might not actually be 0, but could be something else entirely?

More accurately put, it isn't said that NULL has to be 0 (or (void *)0 for that matter) by the standard. What actualy is a NULL pointer is, as far as the C standard is concerned, system dependent, although when comparing integers and pointers the integer 0 is mapped onto the NULL pointer.

That said, there aren't many computer systems in use today that I'm aware of that don't have a NULL pointer that is actually 0.

Zaphos
Member #1,468
August 2001

Hmm, but Bjarne Stroustrup recommends the use of 0 instead of NULL, at least in C++, which implies that 0 can be used as NULL even if NULL is not defined to be 0? Or was Bjarne just wrong ... or does that only apply to C++?

Evert
Member #794
November 2000
avatar

Well, Bjarne Stroustrup is an idiot ;)
Anyway, the integer 0, when cast to a pointer, becomes the NULL pointer (this is more or less what I meant when I talked about comparisons above).
So although the bytes that make up a NULL pointer aren't nescessarily 0, assigning 0 to a pointer will still make it a NULL pointer.

I prefer NULL over 0 any time because to me there is a logical distinction between the integer 0 and a NULL pointer and making this distinction in code improves readability.

gnolam
Member #2,030
March 2002
avatar

Quote:

Doesn't it say somewhere that NULL (which is a special value) might not actually be 0, but could be something else entirely?

Yep. The internal machine representation could be 0xDEADDEAD or something for all that we care, but in the code it is always safe to assume that NULL == 0.

I still find it cleaner to use NULL instead of 0 though... it makes it clear that what I'm dealing with is a pointer and not something else.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Gideon Weems
Member #3,925
October 2003

Quote:

A NULL pointer is not the same thing as an empty string. The '\0' character is sometimes also referred to as null or nil, but it is different from a NULL pointer.

True, but I was coming from the perspective of a compiler:

char *ch = NULL;
if(ch == '\0')
    printf("%s == %s", ch, '\0');

I thought it was safe to assume that '\0' == 0. Taking gnolam's word that in the code it's safe to assume that NULL == 0, I don't see the difference; it's transitive.

Evert
Member #794
November 2000
avatar

Quote:

I thought it was safe to assume that '\0' == 0.

Technically, it's not. That's why you should use '\0' instead of 0.

Although for all practical purposes NULL = 0 = '\0', they mean something different in principle - and getting those mixed up is bad.

Your code for example doesn't make the distinction, which causes bad things to happen.

Because the pointer is NULL doesn't mean that the string is an empty one (you don't know what is stored at memory location 0 - ok, actually, you could know that by looking it up).
In the code you posted, printf() will dereference the NULL pointer, which is always an error.
Maybe I'm being redundant, but just to sumarize the distinction:

char *s_empty = "";
char *s_null = NULL;

Now the first points to some memory location, where the value '\0' isstored:
s_empty -> 0x66666666 ['\0']
The second points to memory location 0, which you don't know about:
s_null -> 0x00000000 [?????]
So while you can compare both pointers, you cannot dereference the second one. This would be true even if NULL weren't a special addres because you don't have permission to access it anyway.

Gideon Weems
Member #3,925
October 2003

I appreciate the explanation. So, how is printf() working? The output of the snippet goes like this "(null) == (null)". Unless you are wrong about printf() dereferencing the null pointer, it seems that the value at address 0 actually is 0, and printf() is designed to print "(null)" when encountering a 0-length string? ... But, that's impossible; a seg fault would occur, right? So, printf() actually doesn't dereference the address if it's 0.

Isn't it granted that address 0 is a no-no, regardless of OS? Maybe printf() is correct in not playing dumb and looking up address 0. But, Allegro needs to be fast and checking the address would be too much extra baggage, so that's out of the question, right?

So, where does the compromise lie? Or, are things good the way they are? I'm starting to think so...

P.S. Wham! I'm a slut when it comes to giving credit...

gillius
Member #119
April 2000

The C++ standard strongly implies the value of a "null pointer" is 0. In fact, the word "NULL" is not a keyword in C++ or something that is even built in. I'm not even positive that null is specified in the C++ standard... I just checked though before I posted to make sure, I did find a reference to it:

TFM said:

The macro NULL, defined in any of <clocale>, <cstddef>, <cstdio>, <cstdlib>, <cstring>,
<ctime>, or <cwchar>, is an implementationdefined
C++ null pointer constant in this International
Standard (18.1).

The NULL macro is not part of C++ (sortof), but instead it is in the section saying that the standard library defined by C is also defined in C++ with the following differences and inclusions.

I tried to find the part that specifically defined the null pointer, but it does seem to imply that the null-pointer and 0 are not identical, but that a null-pointer always evaluates to "0" and vice versa, and that the null-pointer to one type is always convertable to the null-pointer of another type:

TFM said:

A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to
zero. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that
type and is distinguishable from every other value of pointer to object or pointer to function type. Two null
pointer values of the same type shall compare equal.

EDIT: I find it interesting that the last quote implies that two null pointer values to different types may not compare equal -- I couldn't find anything that does. That means the following program has undefined behavior in C++, from how I interpet that:

int* p1 = 0;  //valid
float* p2 = 0;//valid
if ( p1 == p2 )//undefined
  cout << "p1 == p2" << endl; //may or may not be executed.

Gillius
Gillius's Programming -- https://gillius.org/

Evert
Member #794
November 2000
avatar

Quote:

EDIT: I find it interesting that the last quote implies that two null pointer values to different types may not compare equal -- I couldn't find anything that does. That means the following program has undefined behavior in C++

This is true of C as well, as far as I know.
There are (or were) computers where different pointer types are really different from each other, so that a float* is different from an int* not just in how they treat what is stored at the target location.
This is different from the i86 architecture where a pointer is just a memory address (integer) based off some selector or segment.

To make safe pointer comparisons, they have to be cast to the same type. I think the only safe typecast is actually a cast to void*, but here I could be mistaken.

 1   2 


Go to: