Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

NULL and zeros

4 views
Skip to first unread message

Yevgen Muntyan

unread,
Oct 2, 2006, 10:51:02 PM10/2/06
to
Hey,

Are there not highly specialized and still existing and used platforms
where NULL is not a sequence of zeros, so that "char *a = NULL;" and
"char *a; memset (&a, 0, sizeof (a));" are not equivalent?

In other words, do I care about possible difference between NULL and
zero-filled pointer if e.g. I assume the target platform can run X
or it is Windows?

Thanks,
Yevgen

Eric Sosman

unread,
Oct 2, 2006, 11:25:56 PM10/2/06
to
Yevgen Muntyan wrote:

Have you read Question 5.17 in the comp.lang.c Frequently
Asked Questions (FAQ) list at <http://c-faq.com/>?

Also, have you read the tenth of the Ten Commandments for
C Programmers at <http://www.plethora.net/~seebs/c/10com.html>?

It takes a tiny bit more effort to zero your pointers portably
than to just use calloc() or memset() and hope for the best -- but
the additional effort *is* tiny, after all! It is unlikely that you
will run across a machine where all-bits-zero is not a null pointer;
it is also unlikely that your house will burn down, yet most people
I know pay for fire insurance. Keep in mind that fashions come and
go in our industry; it would be risky to assume that progress has
ceased and that machines of the future will be just like those of
today.

--
Eric Sosman
eso...@acm-dot-org.invalid

Cong Wang

unread,
Oct 2, 2006, 11:27:08 PM10/2/06
to

See FAQ of comp.lang.c:<http://c-faq.com>. Question 5.5 may be useful
for you.

Yevgen Muntyan

unread,
Oct 2, 2006, 11:56:35 PM10/2/06
to
Eric Sosman wrote:
> Yevgen Muntyan wrote:
>
>> Hey,
>>
>> Are there not highly specialized and still existing and used platforms
>> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
>> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?
>>
>> In other words, do I care about possible difference between NULL and
>> zero-filled pointer if e.g. I assume the target platform can run X
>> or it is Windows?
>
>
> Have you read Question 5.17 in the comp.lang.c Frequently
> Asked Questions (FAQ) list at <http://c-faq.com/>?
>
> Also, have you read the tenth of the Ten Commandments for
> C Programmers at <http://www.plethora.net/~seebs/c/10com.html>?

I have read those, and it's why I'm asking. Question is: is true
*hypothetical* portability more important than convenience in my
specific case?
For example, I do understand that it's silly to assume everything is
32-bits PC, but you should admit that it's quite reasonable to assume
that target win32 platform has sizeof(void*) == 32 (and I am not talking
about some code potentially ported to other platforms, no, code which
does HANDLE a = Blah()).

In my specific case, I am using glib and gtk libraries which assume
8-bits bytes and ASCII (i.e. will break on EBCDIC). And I do use
ASCII table when deal with characters (in a terminal emulator for
instance); sometimes I use 8 instead of sizeof(char); I even assume
sometimes that int is at least 32 bits! Maybe it's
evil/bad/ignorant/kills kittens, but I am not going to stop using
ASCII table just because not everything is ASCII, since it simply
doesn't make sense in my setup.

> It takes a tiny bit more effort to zero your pointers portably
> than to just use calloc() or memset() and hope for the best -- but
> the additional effort *is* tiny, after all!

It's lot of lines of obj->this = NULL; obj->that = NULL;
I get zero-initialized structures for free and would really love
not to have to initialize all pointers inside. Besides, lot of
NULL initializations makes code actually harder to modify - you need
to consult header to know whether you got all should-be-NULL actually
NULL's.

Best regards,
Yevgen

Barry Schwarz

unread,
Oct 3, 2006, 12:54:44 AM10/3/06
to
On Tue, 03 Oct 2006 03:56:35 GMT, Yevgen Muntyan
<muntyan.r...@tamu.edu> wrote:

>Eric Sosman wrote:
>> Yevgen Muntyan wrote:
>>
>>> Hey,
>>>
>>> Are there not highly specialized and still existing and used platforms
>>> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
>>> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?
>>>
>>> In other words, do I care about possible difference between NULL and
>>> zero-filled pointer if e.g. I assume the target platform can run X
>>> or it is Windows?
>>
>>
>> Have you read Question 5.17 in the comp.lang.c Frequently
>> Asked Questions (FAQ) list at <http://c-faq.com/>?
>>
>> Also, have you read the tenth of the Ten Commandments for
>> C Programmers at <http://www.plethora.net/~seebs/c/10com.html>?
>
>I have read those, and it's why I'm asking. Question is: is true
>*hypothetical* portability more important than convenience in my
>specific case?

It depends on what you want to do with the code.

Will you post it here asking for help? Will the one person
who has solved your problem just a day or two ago be prevented from
testing the solution on your code because his system does not match
your assumptions.

Will your code be used long enough to see a new version of
the compiler and run-time library?

Will you, or your employer, ever want to port the code to a
different system?

If you develop sloppy habits now, will you recognize them and have the
discipline to change when portability becomes more than a
"hypothetical" issue?

>For example, I do understand that it's silly to assume everything is
>32-bits PC, but you should admit that it's quite reasonable to assume
>that target win32 platform has sizeof(void*) == 32 (and I am not talking
>about some code potentially ported to other platforms, no, code which
>does HANDLE a = Blah()).
>
>In my specific case, I am using glib and gtk libraries which assume
>8-bits bytes and ASCII (i.e. will break on EBCDIC). And I do use
>ASCII table when deal with characters (in a terminal emulator for
>instance); sometimes I use 8 instead of sizeof(char); I even assume

Since sizeof(char) is always one, this must produce interesting
results.

>sometimes that int is at least 32 bits! Maybe it's
>evil/bad/ignorant/kills kittens, but I am not going to stop using
>ASCII table just because not everything is ASCII, since it simply
>doesn't make sense in my setup.
>
>> It takes a tiny bit more effort to zero your pointers portably
>> than to just use calloc() or memset() and hope for the best -- but
>> the additional effort *is* tiny, after all!
>
>It's lot of lines of obj->this = NULL; obj->that = NULL;
>I get zero-initialized structures for free and would really love
>not to have to initialize all pointers inside. Besides, lot of
>NULL initializations makes code actually harder to modify - you need
>to consult header to know whether you got all should-be-NULL actually
>NULL's.
>

You appear to be looking for someone to bless your decision to make
unnecessary non-portable assumptions. I believe it was Johnny Cash
who said "It ain't me, babe".


Remove del for email

Walter Roberson

unread,
Oct 3, 2006, 2:50:53 AM10/3/06
to
In article <9iq3i216q6kgs2te6...@4ax.com>,
Barry Schwarz <schw...@doezl.net> wrote:

>You appear to be looking for someone to bless your decision to make
>unnecessary non-portable assumptions. I believe it was Johnny Cash
>who said "It ain't me, babe".

Johnny Cash did cover that, but it is a 1964 Bob Dylan song.
http://en.wikipedia.org/wiki/It_Ain't_Me_Babe
--
"It is important to remember that when it comes to law, computers
never make copies, only human beings make copies. Computers are given
commands, not permission. Only people can be given permission."
-- Brad Templeton

Peter Nilsson

unread,
Oct 3, 2006, 3:10:02 AM10/3/06
to
Yevgen Muntyan wrote:
> Eric Sosman wrote:
> > Yevgen Muntyan wrote:
> >> Are there not highly specialized and still existing and used platforms
> >> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
> >> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?
> >>
> >> In other words, do I care about possible difference between NULL and
> >> zero-filled pointer if e.g. I assume the target platform can run X
> >> or it is Windows?
<snip>

> > It takes a tiny bit more effort to zero your pointers portably
> > than to just use calloc() or memset() and hope for the best -- but
> > the additional effort *is* tiny, after all!
>
> It's lot of lines of obj->this = NULL; obj->that = NULL;
> I get zero-initialized structures for free

In what sense are they 'free'? Most callocs still have to zero the
address space. So there is a cost.

> and would really love
> not to have to initialize all pointers inside. Besides, lot of
> NULL initializations makes code actually harder to modify - you need
> to consult header to know whether you got all should-be-NULL actually
> NULL's.

struct whatever *array = malloc(N * sizeof *array);
if (!array) return 0;
for (i = 0; i < N; i++)
{
static const struct whatever zero_k = { 0 };
array[i] = zero_k; /* look ma, nothing missed */

/* non-zero initialisation */
}

[In C99 it's even easier!]

I remember Chris Torek once pointing out that hardware engineers
have a habit of reusing old ideas in new technologies.

Ask yourself, what is special about all-bits-zero on modern cpus?
Why not all ones say?

You want us to give a categorical reason for why future
implementations might change from using all bits zero
as null pointer representations? I think you'll have a harder
task giving us a categorical reason for why they wouldn't
ever change. ;-)

I'm not saying they will change, I'm just saying I can't
see any strong reason preventing the possibility. And
someone once saw a reason in the past...

--
Peter

Yevgen Muntyan

unread,
Oct 3, 2006, 3:55:49 AM10/3/06
to
Peter Nilsson wrote:
> Yevgen Muntyan wrote:
>
>>Eric Sosman wrote:
>>
>>>Yevgen Muntyan wrote:
>>>
>>>>Are there not highly specialized and still existing and used platforms
>>>>where NULL is not a sequence of zeros, so that "char *a = NULL;" and
>>>>"char *a; memset (&a, 0, sizeof (a));" are not equivalent?
>>>>
>>>>In other words, do I care about possible difference between NULL and
>>>>zero-filled pointer if e.g. I assume the target platform can run X
>>>>or it is Windows?
>
> <snip>
>
>>> It takes a tiny bit more effort to zero your pointers portably
>>>than to just use calloc() or memset() and hope for the best -- but
>>>the additional effort *is* tiny, after all!
>>
>>It's lot of lines of obj->this = NULL; obj->that = NULL;
>>I get zero-initialized structures for free
>
>
> In what sense are they 'free'? Most callocs still have to zero the
> address space. So there is a cost.

They are free in the sense I get calloc'ed structures even if I don't
want it (it's glib api, no choice on my side). And for a GUI application
time spent in malloc(), calloc(), or malloc() with consequent zeroing by
memset() is usually the same (zero).

What happens is: the library creates an object and calls an init
function supplied by me, so it does something like:

obj = calloc (1, sizeof (MyStruct));
my_init (obj);

and then my job is

void my_init (MyStruct *obj)
{
obj->foo = NULL;
obj->bar = 2;
...
}

I don't like putting obj->foo = NULL in there. Then, if I don't
explicitely initialize NULL pointers here, I tend to use calloc()
in other places too.

It might be also because of the fact that I started with C++, and
then switched to C, default-initialized structure member is a really
cool feature (I hope noone will say "so go use C++ if you don't like
C" or something).

>>and would really love
>>not to have to initialize all pointers inside. Besides, lot of
>>NULL initializations makes code actually harder to modify - you need
>>to consult header to know whether you got all should-be-NULL actually
>>NULL's.
>
>
> struct whatever *array = malloc(N * sizeof *array);
> if (!array) return 0;
> for (i = 0; i < N; i++)
> {
> static const struct whatever zero_k = { 0 };
> array[i] = zero_k; /* look ma, nothing missed */
>
> /* non-zero initialisation */
> }
>
> [In C99 it's even easier!]

This code immediately creates a question: "What the heck? What's that
static thing?" It's much worse than honest

thing->this = NULL;
thing->that = NULL;

>
> I remember Chris Torek once pointing out that hardware engineers
> have a habit of reusing old ideas in new technologies.
>
> Ask yourself, what is special about all-bits-zero on modern cpus?
> Why not all ones say?

Well, fact that zero is used instead of one makes it special. Why it
happens, I have no idea. Maybe because it's natural? Zero is so nice,
so nothing.

> You want us to give a categorical reason for why future
> implementations might change from using all bits zero
> as null pointer representations? I think you'll have a harder
> task giving us a categorical reason for why they wouldn't
> ever change. ;-)

Nah, I asked if there are *existing* platforms where NULL and
zero-filled pointer are not the same.
I really seriously asked about exactly that. I have dealt only with
four platforms and five or six operating systems, so I naturally wonder
if this zero-NULL thing is common for all "popular" devices/compilers
or it's just an accidental thing on those "big" computers I've used.

It looks like this thread indeed confirms that I'm safe (now of course).

Best regards,
Yevgen

Keith Thompson

unread,
Oct 3, 2006, 4:08:45 AM10/3/06
to
Yevgen Muntyan <muntyan.r...@tamu.edu> writes:
> Eric Sosman wrote:
>> Yevgen Muntyan wrote:
>>> Are there not highly specialized and still existing and used platforms
>>> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
>>> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?
>>>
>>> In other words, do I care about possible difference between NULL and
>>> zero-filled pointer if e.g. I assume the target platform can run X
>>> or it is Windows?
>> Have you read Question 5.17 in the comp.lang.c Frequently
>> Asked Questions (FAQ) list at <http://c-faq.com/>?
>> Also, have you read the tenth of the Ten Commandments for
>> C Programmers at <http://www.plethora.net/~seebs/c/10com.html>?
>
> I have read those, and it's why I'm asking. Question is: is true
> *hypothetical* portability more important than convenience in my
> specific case?

How much convenience does it really buy you?

> For example, I do understand that it's silly to assume everything is
> 32-bits PC, but you should admit that it's quite reasonable to assume
> that target win32 platform has sizeof(void*) == 32 (and I am not talking
> about some code potentially ported to other platforms, no, code which
> does HANDLE a = Blah()).

Well, sizeof(void*) is more likely to be 4 (it counts bytes, not
bits). But why do you need to *assume* that void* is 32 bits? If you
need to know how big void* is, use "sizeof(void*)".

I'm not familiar with Win32, but isn't there also a Win64 interface,
and wouldn't you want your code to be able to work with it?

> In my specific case, I am using glib and gtk libraries which assume
> 8-bits bytes and ASCII (i.e. will break on EBCDIC). And I do use
> ASCII table when deal with characters (in a terminal emulator for
> instance); sometimes I use 8 instead of sizeof(char); I even assume
> sometimes that int is at least 32 bits! Maybe it's
> evil/bad/ignorant/kills kittens, but I am not going to stop using
> ASCII table just because not everything is ASCII, since it simply
> doesn't make sense in my setup.

You mean CHAR_BIT, not sizeof(char) (which is 1 by definition).

You almost certainly don't need to depend on ASCII for printable
characters; that's what character constants are for. For control
characters, though, it's sensible to depend on, for example, the
escape character being '\x1b'. I'd use a macro, and I'd try to
isolate the code.

You might consider something like:

#if CHAR_BIT != 8
#error CHAR_BIT != 8
#endif

>> It takes a tiny bit more effort to zero your pointers portably
>> than to just use calloc() or memset() and hope for the best -- but
>> the additional effort *is* tiny, after all!
>
> It's lot of lines of obj->this = NULL; obj->that = NULL;
> I get zero-initialized structures for free and would really love
> not to have to initialize all pointers inside. Besides, lot of
> NULL initializations makes code actually harder to modify - you need
> to consult header to know whether you got all should-be-NULL actually
> NULL's.

How do you get zero-initialized structures for free?

Static objects are initialized to zero; for structures, each member is
initialized to zero converted to the appropriate type, and recursively
for sub-structures. Pointers are initialized to null even if null is
something other than all-bits-zero.

For example:

struct foo {
int i;
double d;
void *p;
};
const struct foo foo_zero = { 0 };

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Yevgen Muntyan

unread,
Oct 3, 2006, 5:02:26 AM10/3/06
to

Yeah, and sizeof(char) == 8 is even better :)

> But why do you need to *assume* that void* is 32 bits? If you
> need to know how big void* is, use "sizeof(void*)".

I've never used constant 32 (well, not for pointers). But, sizeof(int)
is also 4, and then you can cast HANDLE (which is void*) into int and
back, and do whatever other nasty stuff you like (sorry, I can't make up
a realistic example, but you can refer to codeproject.com to find some
nice code).

> I'm not familiar with Win32, but isn't there also a Win64 interface,
> and wouldn't you want your code to be able to work with it?

Microsoft takes care of win32 binaries working on win64.

>>In my specific case, I am using glib and gtk libraries which assume
>>8-bits bytes and ASCII (i.e. will break on EBCDIC). And I do use
>>ASCII table when deal with characters (in a terminal emulator for
>>instance); sometimes I use 8 instead of sizeof(char); I even assume
>>sometimes that int is at least 32 bits! Maybe it's
>>evil/bad/ignorant/kills kittens, but I am not going to stop using
>>ASCII table just because not everything is ASCII, since it simply
>>doesn't make sense in my setup.
>
>
> You mean CHAR_BIT, not sizeof(char) (which is 1 by definition).
>
> You almost certainly don't need to depend on ASCII for printable
> characters; that's what character constants are for.

Of course it's not about individual characters.
In ASCII, printable characters are from 32 to 126; EBCDIC uses some
completely strange order, with some strange gaps (perhaps you need
to remove/add some bit to get something sensible). Moreover, ASCII
printable characters live in intersection of signed and unsigned char,
so you can do

unsigned ch = get_it_somehow();
if (' ' <= ch && ch <= '~')
do_something();

(if I didn't mess up in there again). Or, 'a' < ch && ch < 'z'
to test whether ch is a lower case letter. I believe it's not
hard in EBCDIC either (perhaps some macros), but why would I care?
I don't even have access to an EBCDIC system, even if I wanted
to play with it.

>
> You might consider something like:
>
> #if CHAR_BIT != 8
> #error CHAR_BIT != 8
> #endif

And I wouldn't be able to test it without screwing up or faking system
headers if I were so serious to insert this useless build error :)

And how is code that doesn't build better than code that builds (would
be real strange if it did) and doesn't work, given that there's a list
of supported platforms all of which have 8-bits bytes? At least buggy
behavior would show that it indeed builds but doesn't work.

>>> It takes a tiny bit more effort to zero your pointers portably
>>>than to just use calloc() or memset() and hope for the best -- but
>>>the additional effort *is* tiny, after all!
>>
>>It's lot of lines of obj->this = NULL; obj->that = NULL;
>>I get zero-initialized structures for free and would really love
>>not to have to initialize all pointers inside. Besides, lot of
>>NULL initializations makes code actually harder to modify - you need
>>to consult header to know whether you got all should-be-NULL actually
>>NULL's.
>
>
> How do you get zero-initialized structures for free?

Sorry, I didn't notice I used "initialized", I meant "zero-filled",
allocated by calloc(), I described it in other post.

Best regards,
Yevgen

Samuel Stearley

unread,
Oct 3, 2006, 5:16:37 AM10/3/06
to
Yevgen Muntyan wrote:
> Well, fact that zero is used instead of one makes it special. Why it
> happens, I have no idea. Maybe because it's natural? Zero is so nice,
> so nothing.


Its really easy to check if a value is zero.
On many CPUs (68k, powerPC, ARMs, probably x86) the load register
instruction is capable of setting the zero flag which a branch can be
done on. This eliminates the need for a compare instruction.

I seriously doubt there will ever be any CPU or Aplication Binary
Interface that defines NULL as non zero.

Richard Heathfield

unread,
Oct 3, 2006, 5:35:29 AM10/3/06
to
Samuel Stearley said:

Really? Check out the FAQs - particularly question 5.17.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Keith Thompson

unread,
Oct 3, 2006, 6:17:05 AM10/3/06
to
Yevgen Muntyan <muntyan.r...@tamu.edu> writes:
> Keith Thompson wrote:
[...]

>> But why do you need to *assume* that void* is 32 bits? If you
>> need to know how big void* is, use "sizeof(void*)".
>
> I've never used constant 32 (well, not for pointers). But, sizeof(int)
> is also 4, and then you can cast HANDLE (which is void*) into int and
> back, and do whatever other nasty stuff you like (sorry, I can't make up
> a realistic example, but you can refer to codeproject.com to find some
> nice code).

No thanks; code that assumes ints and pointers are the same size
doesn't meet my definition of "nice".

C99 provides a type intptr_t which is guaranteed to be able to hold a
pointer value. If your implementation doesn't define intptr_t, you
can define it yourself. Define it as int if you like; you'll be able
to change it if, some day, you need to compile your code on another
system.

>> I'm not familiar with Win32, but isn't there also a Win64 interface,
>> and wouldn't you want your code to be able to work with it?
>
> Microsoft takes care of win32 binaries working on win64.

I care more about source portability. I'm guessing that recompiling
to a win64 binary will give you better code.

>>>In my specific case, I am using glib and gtk libraries which assume
>>>8-bits bytes and ASCII (i.e. will break on EBCDIC). And I do use
>>>ASCII table when deal with characters (in a terminal emulator for
>>>instance); sometimes I use 8 instead of sizeof(char); I even assume
>>>sometimes that int is at least 32 bits! Maybe it's
>>>evil/bad/ignorant/kills kittens, but I am not going to stop using
>>>ASCII table just because not everything is ASCII, since it simply
>>>doesn't make sense in my setup.
>>
>>
>> You mean CHAR_BIT, not sizeof(char) (which is 1 by definition).
>>
>> You almost certainly don't need to depend on ASCII for printable
>> characters; that's what character constants are for.
>
> Of course it's not about individual characters.
> In ASCII, printable characters are from 32 to 126; EBCDIC uses some
> completely strange order, with some strange gaps (perhaps you need
> to remove/add some bit to get something sensible). Moreover, ASCII
> printable characters live in intersection of signed and unsigned char,
> so you can do
>
> unsigned ch = get_it_somehow();
> if (' ' <= ch && ch <= '~')
> do_something();

That's what isprint() is for.

> (if I didn't mess up in there again). Or, 'a' < ch && ch < 'z'
> to test whether ch is a lower case letter. I believe it's not
> hard in EBCDIC either (perhaps some macros), but why would I care?
> I don't even have access to an EBCDIC system, even if I wanted
> to play with it.

Use islower().

>> You might consider something like:
>>
>> #if CHAR_BIT != 8
>> #error CHAR_BIT != 8
>> #endif
>
> And I wouldn't be able to test it without screwing up or faking system
> headers if I were so serious to insert this useless build error :)
>
> And how is code that doesn't build better than code that builds (would
> be real strange if it did) and doesn't work, given that there's a list
> of supported platforms all of which have 8-bits bytes? At least buggy
> behavior would show that it indeed builds but doesn't work.

I like to catch errors as early as possible. If you'd rather waste
your time tracking down run-time bugs, that's up to you.

Harald van Dijk

unread,
Oct 3, 2006, 7:54:21 AM10/3/06
to
Keith Thompson wrote:
> Yevgen Muntyan <muntyan.r...@tamu.edu> writes:
> > Keith Thompson wrote:
> >> You almost certainly don't need to depend on ASCII for printable
> >> characters; that's what character constants are for.
> >
> > Of course it's not about individual characters.
> > In ASCII, printable characters are from 32 to 126; EBCDIC uses some
> > completely strange order, with some strange gaps (perhaps you need
> > to remove/add some bit to get something sensible). Moreover, ASCII
> > printable characters live in intersection of signed and unsigned char,
> > so you can do
> >
> > unsigned ch = get_it_somehow();
> > if (' ' <= ch && ch <= '~')
> > do_something();
>
> That's what isprint() is for.
>
> > (if I didn't mess up in there again). Or, 'a' < ch && ch < 'z'
> > to test whether ch is a lower case letter. I believe it's not
> > hard in EBCDIC either (perhaps some macros), but why would I care?
> > I don't even have access to an EBCDIC system, even if I wanted
> > to play with it.
>
> Use islower().

Mainly just out of curiosity: what would you use to print all words in
a file, where the file may contain multi-byte character sequences, but
your definition of "word" does not allow for characters outside of the
English alphabet?

Ancient_Hacker

unread,
Oct 3, 2006, 8:01:34 AM10/3/06
to

Yevgen Muntyan wrote:
> Hey,
>
> Are there not highly specialized and still existing and used platforms
> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?


I can't think of any right offhand, but any architecture that has
capability-style pointers, or segmented pointers could conceivably have
pointers that have a non-0 bit pattern.

The problem is, the dung-cart is pushing the horse these days-- the
(commercial) guys that dream up lines on silicon are not going to waste
space on anything that a C compiler won't emit. And non-zero NULL
pointers are not at all popular. So it's a bit of a
South-of-the-border imbroglio.

There may be the occasional chip brewed up at Stanford that has nice
features like structured address spaces, capability bits on each byte,
range checking, etc, but we're likely to be stuck with the very fast
and dumb CPU's targeted by C-like languages and policies.

Eric Sosman

unread,
Oct 3, 2006, 8:07:57 AM10/3/06
to
Yevgen Muntyan wrote:
> Eric Sosman wrote:
>
>> Yevgen Muntyan wrote:
>>
>>> Hey,
>>>
>>> Are there not highly specialized and still existing and used platforms
>>> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
>>> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?
>>>
>>> In other words, do I care about possible difference between NULL and
>>> zero-filled pointer if e.g. I assume the target platform can run X
>>> or it is Windows?
>>
>> Have you read Question 5.17 in the comp.lang.c Frequently
>> Asked Questions (FAQ) list at <http://c-faq.com/>?
>>
>> Also, have you read the tenth of the Ten Commandments for
>> C Programmers at <http://www.plethora.net/~seebs/c/10com.html>?
>
>
> I have read those, and it's why I'm asking. Question is: is true
> *hypothetical* portability more important than convenience in my
> specific case?

It comes down to how highly you value convenience and how
highly you value portability. That is, it comes down to two
matters of your own tastes and desires, not to the experiences
of other people. So why ask at all? It's like asking "Should
I prefer apples or oranges?"

> It's lot of lines of obj->this = NULL; obj->that = NULL;
> I get zero-initialized structures for free and would really love
> not to have to initialize all pointers inside. Besides, lot of
> NULL initializations makes code actually harder to modify - you need
> to consult header to know whether you got all should-be-NULL actually
> NULL's.

If you want to initialize a struct without knowing what elements
the struct contains, you're on shaky ground already. It seems you
may be worried about

void init_struct(struct s *ptr) {
ptr->p1 = NULL;
ptr->p2 = NULL;
}

... where somebody might come along at a later date and add a p3
element, which would then go uninitialized unless he also remembered
to modify init_struct(). If that's the issue, I've got two answers:
First, somebody who modifies a data structure should also take the
responsibility of keeping its "constructors" and "renderers" and so
on up-to-date, and the code should be arranged in such a way that
the data type's "fundamental operators" are easy to find -- in fact,
hard for him to avoid. That's really a social problem, not a
programming problem, and you need to employ social pressures like
coding standards to keep the problem under control.

Second, a technical solution for the special case where you'd
like to initialize to "all members zero" (which may or may not be
"all bits zero") without worrying about the elements individually:

void init_struct(struct s *ptr) {
static const struct s all_zeroes;
*ptr = all_zeroes;
}

Which do you like more? Or do you prefer calloc()? Apples,
oranges, or pears?

--
Eric Sosman
eso...@acm-dot-org.invalid

mark_b...@pobox.com

unread,
Oct 3, 2006, 9:13:52 AM10/3/06
to

Samuel Stearley wrote:

> I seriously doubt there will ever be any CPU or Aplication Binary
> Interface that defines NULL as non zero.

I used to work on Prime, so I can definitively say you are mistaken.

The memory model does not need to be a flat one, like an array.

Someone

unread,
Oct 3, 2006, 11:23:27 AM10/3/06
to
Keith Thompson wrote:
> Yevgen Muntyan <muntyan.r...@tamu.edu> writes:
>
>>Keith Thompson wrote:
>
> [...]
>
>>>But why do you need to *assume* that void* is 32 bits? If you
>>>need to know how big void* is, use "sizeof(void*)".
>>
>>I've never used constant 32 (well, not for pointers). But, sizeof(int)
>>is also 4, and then you can cast HANDLE (which is void*) into int and
>>back, and do whatever other nasty stuff you like (sorry, I can't make up
>>a realistic example, but you can refer to codeproject.com to find some
>>nice code).
>
>
> No thanks; code that assumes ints and pointers are the same size
> doesn't meet my definition of "nice".

Um, "nice code" should read "awful win32 code".

> C99 provides a type intptr_t which is guaranteed to be able to hold a
> pointer value. If your implementation doesn't define intptr_t, you
> can define it yourself. Define it as int if you like; you'll be able
> to change it if, some day, you need to compile your code on another
> system.

This sounds just like how people write win32 code - define stuff as they
like (just then never change it). I do compile my code "on another
system". And I use stuff supplied by glib, it's more reliable.

>>>I'm not familiar with Win32, but isn't there also a Win64 interface,
>>>and wouldn't you want your code to be able to work with it?
>>
>>Microsoft takes care of win32 binaries working on win64.
>
>
> I care more about source portability. I'm guessing that recompiling
> to a win64 binary will give you better code.

Point is: you don't need to worry about win64 at all if you don't need
its features, it's not like x86 vs amd64 linux, where you actually want
your code be compiled on amd64, and you have to forget about "everything
is 32-bits". By the way, caring about portable windows code is really
funny. There's no portable windows code ;)
Yes, writing code without assuming it's gonna run on 32-bits PC is good,
but using some win32 code that does assume 32 bits is not real bad
either, in case that code does what it should do.

>>>>In my specific case, I am using glib and gtk libraries which assume
>>>>8-bits bytes and ASCII (i.e. will break on EBCDIC). And I do use
>>>>ASCII table when deal with characters (in a terminal emulator for
>>>>instance); sometimes I use 8 instead of sizeof(char); I even assume
>>>>sometimes that int is at least 32 bits! Maybe it's
>>>>evil/bad/ignorant/kills kittens, but I am not going to stop using
>>>>ASCII table just because not everything is ASCII, since it simply
>>>>doesn't make sense in my setup.
>>>
>>>
>>>You mean CHAR_BIT, not sizeof(char) (which is 1 by definition).
>>>
>>>You almost certainly don't need to depend on ASCII for printable
>>>characters; that's what character constants are for.
>>
>>Of course it's not about individual characters.
>>In ASCII, printable characters are from 32 to 126; EBCDIC uses some
>>completely strange order, with some strange gaps (perhaps you need
>>to remove/add some bit to get something sensible). Moreover, ASCII
>>printable characters live in intersection of signed and unsigned char,
>>so you can do
>>
>>unsigned ch = get_it_somehow();
>>if (' ' <= ch && ch <= '~')
>> do_something();
>
>
> That's what isprint() is for.

No it's not. isprint() is locale dependent, it's not for detecting
printable ASCII characters (or printable UTF8 1-byte characters,
to make it funnier, C doesn't give UTF8). There's isascii() though (not
standard, is it?), so you really can use only issomething() C calls;
e.g. isascii(ch) && islower(ch) detects lowercase letter.

Question: what does it buy except *false* feeling of safety with
regard to portability (false because used library is not portable)?

(I do not use wchar, I almost always work with UTF8, so iswsomething()
family is irrelevant too).

>>(if I didn't mess up in there again). Or, 'a' < ch && ch < 'z'
>>to test whether ch is a lower case letter. I believe it's not
>>hard in EBCDIC either (perhaps some macros), but why would I care?
>>I don't even have access to an EBCDIC system, even if I wanted
>>to play with it.
>
>
> Use islower().

See above.

>>>You might consider something like:
>>>
>>>#if CHAR_BIT != 8
>>>#error CHAR_BIT != 8
>>>#endif
>>
>>And I wouldn't be able to test it without screwing up or faking system
>>headers if I were so serious to insert this useless build error :)
>>
>>And how is code that doesn't build better than code that builds (would
>>be real strange if it did) and doesn't work, given that there's a list
>>of supported platforms all of which have 8-bits bytes? At least buggy
>>behavior would show that it indeed builds but doesn't work.
>
>
> I like to catch errors as early as possible. If you'd rather waste
> your time tracking down run-time bugs, that's up to you.

Nah, don't generalize. Imagine that some user bought a brand new
64-bits-per-byte machine in year 2045, and tries to compile your code.
What would be more useful: confirmation that your code is broken (and
you *must* assume that even if you are trying to always write super
portable code) or useless report "it doesn't build"?

How exactly that #error thing catches bugs? How #error can ever help
anything but preventing useless bugs reports (if they are useless,
in this case they would be useful).

Best regards,
Yevgen

Yevgen Muntyan

unread,
Oct 3, 2006, 11:38:48 AM10/3/06
to
Eric Sosman wrote:

> Yevgen Muntyan wrote:
>
>> Eric Sosman wrote:
>>
>>> Yevgen Muntyan wrote:
>>>
>>>> Hey,
>>>>
>>>> Are there not highly specialized and still existing and used platforms
>>>> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
>>>> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?
>>>>
>>>> In other words, do I care about possible difference between NULL and
>>>> zero-filled pointer if e.g. I assume the target platform can run X
>>>> or it is Windows?
>>>
>>>
>>> Have you read Question 5.17 in the comp.lang.c Frequently
>>> Asked Questions (FAQ) list at <http://c-faq.com/>?
>>>
>>> Also, have you read the tenth of the Ten Commandments for
>>> C Programmers at <http://www.plethora.net/~seebs/c/10com.html>?
>>
>>
>>
>> I have read those, and it's why I'm asking. Question is: is true
>> *hypothetical* portability more important than convenience in my
>> specific case?
>
>
> It comes down to how highly you value convenience and how
> highly you value portability.

I am not writing code which depends only on C library. In this case
it depends on GTK library, and "portability" means "works on any
GTK-supported platform". If it's cheap to write portable code, it's
better to write portable code; if it's cheaper to assume bytes
are 8 bits, it's better to assume that. Exactly what you said, except
that "portability" is "real portability", not "portable to any
possible computer with C compiler".

> That is, it comes down to two
> matters of your own tastes and desires, not to the experiences
> of other people. So why ask at all? It's like asking "Should
> I prefer apples or oranges?"

Did I ask that (not sure what)?

>> It's lot of lines of obj->this = NULL; obj->that = NULL;
>> I get zero-initialized structures for free and would really love
>> not to have to initialize all pointers inside. Besides, lot of
>> NULL initializations makes code actually harder to modify - you need
>> to consult header to know whether you got all should-be-NULL actually
>> NULL's.
>
>
> If you want to initialize a struct without knowing what elements
> the struct contains, you're on shaky ground already. It seems you
> may be worried about
>
> void init_struct(struct s *ptr) {
> ptr->p1 = NULL;
> ptr->p2 = NULL;
> }
>
> ... where somebody might come along at a later date and add a p3
> element, which would then go uninitialized unless he also remembered
> to modify init_struct().

No, I modify it all the time ("active development" phase), and I do
forget to put NULL initializers for new structure members, and I hate
removing useless obj->something = NULL; lines, and I don't like seeing
those either. Now, it's really a problem of not having nice design.
"Sloppy design, sloppy code" you might say. Or, "RAD", others may say ;)

> If that's the issue, I've got two answers:
> First, somebody who modifies a data structure should also take the
> responsibility of keeping its "constructors" and "renderers" and so
> on up-to-date, and the code should be arranged in such a way that
> the data type's "fundamental operators" are easy to find -- in fact,
> hard for him to avoid.

Yes, those init() functions are very easy to find, no problem
with that. But having useless lines of code is a problem. It is useless,
you know it's useless, so naturally you stop caring about it (not
intentionally, no, you are good person, it's just laziness and such)
and you need to remember about portability and force yourself to do the
"right" thing. It's much easier not to make "bad" things when you know
they actually hurt someone, you know.

> Which do you like more? Or do you prefer calloc()? Apples,
> oranges, or pears?

Apples. Are there blue oranges with melon taste yet? And do I care
about those hypothetical artificial fruits?

Best regards,
Yevgen

Christopher Layne

unread,
Oct 3, 2006, 12:42:17 PM10/3/06
to
Yevgen Muntyan wrote:
> I am not writing code which depends only on C library. In this case
> Yes, those init() functions are very easy to find, no problem
> with that. But having useless lines of code is a problem. It is useless,
> you know it's useless, so naturally you stop caring about it (not
> intentionally, no, you are good person, it's just laziness and such)
> and you need to remember about portability and force yourself to do the
> "right" thing. It's much easier not to make "bad" things when you know
> they actually hurt someone, you know.

How is:

x->p = NULL;

Useless?

If anything, it's more useful than:

x = calloc(1, sizeof *x);

I presume you're tying "useless" to "unnecessary." If it really bothers you
all that much, #ifdef it out by doing a NULL = (void *)0 check somewhere
else. Otherwise you're sweating the small stuff and probably pre-optimizing
somewhere. Go for portability.

Christopher Layne

unread,
Oct 3, 2006, 12:47:40 PM10/3/06
to
Keith Thompson wrote:

> Static objects are initialized to zero; for structures, each member is
> initialized to zero converted to the appropriate type, and recursively
> for sub-structures. Pointers are initialized to null even if null is
> something other than all-bits-zero.
>
> For example:
>
> struct foo {
> int i;
> double d;
> void *p;
> };
> const struct foo foo_zero = { 0 };

Also, couldn't he just init a global object with the standard inits he wants,
and memcpy it into place after malloc()? I mean, if per-member initialization
is such a big deal and he's worried about machines with NULL == (void *)1564.
Personally I think a global default is kind of "ghetto." but hey, if it
really bothers him that much to init each member.

Christopher Layne

unread,
Oct 3, 2006, 12:50:03 PM10/3/06
to
Someone wrote:
> How exactly that #error thing catches bugs? How #error can ever help
> anything but preventing useless bugs reports (if they are useless,
> in this case they would be useful).
>
> Best regards,
> Yevgen

You're looking for silver bullets to handle all cases. Real-world != like
that. Make a best effort at reasonable portability - or become so anal about
it you never end up getting anything done; your choice.

Christopher Layne

unread,
Oct 3, 2006, 12:59:49 PM10/3/06
to
Yevgen Muntyan wrote:

> I don't like putting obj->foo = NULL in there. Then, if I don't
> explicitely initialize NULL pointers here, I tend to use calloc()
> in other places too.

My only answer here is:

Get over it.

Either suck it up and start assigning NULL if you're concerned about
portability or stop crying about it and be 98% portable. You're only worried
about it because you think it's somehow slowly things down.

Frederick Gotham

unread,
Oct 3, 2006, 1:12:09 PM10/3/06
to
Yevgen Muntyan posted:

> Are there not highly specialized and still existing and used platforms
> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?


Firstly, I'm unaware of the prevalence of implementations where the null
pointer is represented as a bit-pattern of all zeros in memory. Nonetheless
though, I am aware that the Standard permits it, and so I take this into
account when writing portable code.

Hypothetically speaking, if you had a machine whose null pointers all 1's,
then your use of memset would not set the pointer to its null pointer
value.


> In other words, do I care about possible difference between NULL and
> zero-filled pointer if e.g. I assume the target platform can run X
> or it is Windows?


If writing portable code, yes. Even if you're not writing portable code
though, it can be quite easy at times to get the best of both worlds. For
instance, just because the following is valid on Windows:

struct MyStruct {
char *ptrs[50];
};

int main(){ struct MyStruct obj; memset(&obj,0,sizeof obj); return 0; }

, doesn't mean that you should use it. Go with the portable solution, which
is actually also superior in this instance:

int main(){ struct MyStruct obj = {0}; return 0;}

--

Frederick Gotham

Frederick Gotham

unread,
Oct 3, 2006, 1:14:37 PM10/3/06
to
Eric Sosman posted:

> It takes a tiny bit more effort to zero your pointers portably
> than to just use calloc() or memset() and hope for the best -- but
> the additional effort *is* tiny, after all!


Please elaborate on that. I don't see how example 1 could be any slower than
example 2...

Example (1):

char *ptrs[50] = {0};

Example (2):

char *ptrs[50]; memset(ptrs,0,sizeof ptrs);

<slight snip>


> it is also unlikely that your house will burn down, yet most people
> I know pay for fire insurance.

And it's even better when it's free!

--

Frederick Gotham

Yevgen Muntyan

unread,
Oct 3, 2006, 1:38:16 PM10/3/06
to
Christopher Layne wrote:
> Yevgen Muntyan wrote:
>> I am not writing code which depends only on C library. In this case
>> Yes, those init() functions are very easy to find, no problem
>> with that. But having useless lines of code is a problem. It is useless,
>> you know it's useless, so naturally you stop caring about it (not
>> intentionally, no, you are good person, it's just laziness and such)
>> and you need to remember about portability and force yourself to do the
>> "right" thing. It's much easier not to make "bad" things when you know
>> they actually hurt someone, you know.
>
> How is:
>
> x->p = NULL;
>
> Useless?

It is useless on given machines after x is allocated with calloc().
Maybe "useless" is not the right word here, I mean something like
"unnecessary extra code which in effect does nothing but eating
valuable screen space" :)

> If anything, it's more useful than:
>
> x = calloc(1, sizeof *x);

In one case, I am provided with a zero-filled structure,
and then my job is to initialize it. And even when I am allocating
it myself, how is

x = malloc (sizeof (MyType));
x->p = NULL;

more useful than

x = calloc (1, sizeof (MyType));

calloc() is actually more useful because you get well-defined object
content, not some random garbage like with malloc() (we are not talking
about speed here), you get NULL pointers for free (on your machine) and
get guaranteed crash or runtime warning from the library (again on your
machine, not on "any machine" where "standard does not guarantee
that...") in case you forgot to initialize some pointer member.

> I presume you're tying "useless" to "unnecessary."
> If it really bothers you
> all that much, #ifdef it out by doing a NULL = (void *)0 check somewhere
> else.

C standard guarantees that NULL == (void*) 0, doesn't it (unless
NULL macro is broken and doesn't denote NULL pointer)? I would need to
do some checks in configure which would discover NULL bit pattern in
runtime. And how would preprocessor check that equality (or does it know
about void)? It doesn't matter though.

> Otherwise you're sweating the small stuff and probably pre-optimizing
> somewhere.

I am not optimizing anything. I don't like the *code* like following:

void do_init (MyStruct *obj)
{
obj->some_linked_list = NULL;
obj->other_linked_list = NULL;
obj->one_more_list = NULL;
obj->and_a_list_again = NULL;
}

given that obj is already zero-filled.

Best regards,
Yevgen

Yevgen Muntyan

unread,
Oct 3, 2006, 1:42:16 PM10/3/06
to
Christopher Layne wrote:
> Someone wrote:
>> How exactly that #error thing catches bugs? How #error can ever help
>> anything but preventing useless bugs reports (if they are useless,
>> in this case they would be useful).
>>
>> Best regards,
>> Yevgen
>
> You're looking for silver bullets to handle all cases. Real-world != like
> that.

Like what? I thought real world is where NULL is zero-filled ;)

> Make a best effort at reasonable portability - or become so anal about
> it you never end up getting anything done; your choice.

Assuming sizeof(int) == 4 is not reasonable, but assuming NULL is
zero-filled may or may not be reasonably portable, and I wanted
to clarify this. I really didn't know it's so obvious and well-known
that all existing machines out there have zero NULL's!

I didn't mean to start a thread about portability issues, really.
I did understand such a discussion may start, but I really wanted
to know this thing about NULL :)

Best regards,
Yevgen

Richard Heathfield

unread,
Oct 3, 2006, 2:22:02 PM10/3/06
to
[much snippage]

Yevgen Muntyan said:

> Christopher Layne wrote:
>>
>> How is:
>>
>> x->p = NULL;
>>
>> Useless?
>
> It is useless on given machines after x is allocated with calloc().

On some machines, that isn't the case. If you are excluding such machines,
you are in the wrong newsgroup.

>> If anything, it's more useful than:
>>
>> x = calloc(1, sizeof *x);
>
> In one case, I am provided with a zero-filled structure,
> and then my job is to initialize it. And even when I am allocating
> it myself, how is
>
> x = malloc (sizeof (MyType));
> x->p = NULL;
>
> more useful than
>
> x = calloc (1, sizeof (MyType));

Neither is useful. The latter doesn't guarantee you a zero-filled struct,
and the first is unsafe.

> calloc() is actually more useful because you get well-defined object
> content,

Only for integer types.

> C standard guarantees that NULL == (void*) 0, doesn't it

No, it guarantees that NULL expands to an implementation-defined null
pointer constant. Since (void *) 0 is indeed an implementation-defined null
pointer constant, it will always compare equal with NULL, but NULL may be
defined as, say, 0.

But it still remains possible for null pointers on the target platform to be
represented by some other bit pattern. On platforms where that is the case,
the compiler must do some magic to ensure that, when it encounters 0 in a
pointer context, it interprets the 0 as "null pointer constant". Thus:

p = 0; /* p is a null pointer */
memset(&p, 0, sizeof p); /* p might now not be a null pointer! */

>> Otherwise you're sweating the small stuff and probably pre-optimizing
>> somewhere.
>
> I am not optimizing anything. I don't like the *code* like following:
>
> void do_init (MyStruct *obj)
> {
> obj->some_linked_list = NULL;
> obj->other_linked_list = NULL;
> obj->one_more_list = NULL;
> obj->and_a_list_again = NULL;
> }
>
> given that obj is already zero-filled.

That is not a given, if it has been allocated via calloc. Anyway, it's
unnecessary. Just write a constructor:

MyStruct *MyStructCreate(void)
{
MyStruct blank = {0};
MyStruct *new = malloc(sizeof *new);
if(new != NULL)
{
*new = blank;
}
return new;
}

Easy.

Christopher Layne

unread,
Oct 3, 2006, 2:27:40 PM10/3/06
to
Yevgen Muntyan wrote:

> I am not optimizing anything. I don't like the code like following:


>
> void do_init (MyStruct *obj)
> {
> obj->some_linked_list = NULL;
> obj->other_linked_list = NULL;
> obj->one_more_list = NULL;
> obj->and_a_list_again = NULL;
> }
>
> given that obj is already zero-filled.

You're intrinsically tying to tie 0 always to NULL. Integer constant 0 or NULL
will be a null pointer constant, but the converse 0 is always the same as
NULL, isn't always the case.

Christopher Layne

unread,
Oct 3, 2006, 2:35:35 PM10/3/06
to
Richard Heathfield wrote:

>> x = malloc (sizeof (MyType));
>> x->p = NULL;
>>
>> more useful than
>>
>> x = calloc (1, sizeof (MyType));
>
> Neither is useful. The latter doesn't guarantee you a zero-filled struct,
> and the first is unsafe.

How is,

1. The first unsafe? (presuming the rest of the members are explicitly
initialized as well)

2. The latter not result in a zero-filled struct? In most calloc()
implementations I've seen, they're just malloc() + memset().

Example:
total = num * size;
return ((mp = malloc(total)) ? memset(mp, 0, total) : mp);

Richard Heathfield

unread,
Oct 3, 2006, 2:40:46 PM10/3/06
to
Christopher Layne said:

> Richard Heathfield wrote:
>
>>> x = malloc (sizeof (MyType));
>>> x->p = NULL;
>>>
>>> more useful than
>>>
>>> x = calloc (1, sizeof (MyType));
>>
>> Neither is useful. The latter doesn't guarantee you a zero-filled struct,
>> and the first is unsafe.
>
> How is,
>
> 1. The first unsafe? (presuming the rest of the members are explicitly
> initialized as well)

You forgot to check the result of the malloc call before relying on it.

>
> 2. The latter not result in a zero-filled struct?

Even assuming the calloc call succeeds (which is not a given), only those
members of the struct that are integer types are guaranteed to be given 0
values.

> In most calloc()
> implementations I've seen, they're just malloc() + memset().

And that's why. All calloc gives you is a block of memory with all-bits-zero
(for which memset is a fairly reasonable implementation technique). But
all-bits-zero doesn't necessarily mean "zero value", for pointer types and
floating point types.

Christopher Layne

unread,
Oct 3, 2006, 2:44:26 PM10/3/06
to
Richard Heathfield wrote:

> You forgot to check the result of the malloc call before relying on it.

Alright, some stuff is implied, no need to bikeshed it.

>> 2. The latter not result in a zero-filled struct?
>
> Even assuming the calloc call succeeds (which is not a given), only those
> members of the struct that are integer types are guaranteed to be given 0
> values.

What? The entire space of the object is going to be set to 0. Since when does
memset() even care about integer types?

>> In most calloc()
>> implementations I've seen, they're just malloc() + memset().
>
> And that's why. All calloc gives you is a block of memory with all-bits-zero
> (for which memset is a fairly reasonable implementation technique). But
> all-bits-zero doesn't necessarily mean "zero value", for pointer types and
> floating point types.

Alright, and on that token, since we're getting fairly ridiculous by now - how
would all-bits-zero on said (funky machines) guarantee integer zero?

If a given machine expressed 0 as all 1s, then wouldn't supplying the value of
0 to memset result in it being set to all 1s?

Richard Heathfield

unread,
Oct 3, 2006, 2:50:23 PM10/3/06
to
Christopher Layne said:

> Richard Heathfield wrote:
>
>> You forgot to check the result of the malloc call before relying on it.
>
> Alright, some stuff is implied,

If I didn't understand that you were implying that, why should the compiler?

> no need to bikeshed it.

I'm sorry you see defensive programming as a minor detail.

>>> 2. The latter not result in a zero-filled struct?
>>
>> Even assuming the calloc call succeeds (which is not a given), only those
>> members of the struct that are integer types are guaranteed to be given 0
>> values.
>
> What? The entire space of the object is going to be set to 0.

No, it's going to be set to all-bits-zero. That isn't guaranteed to be 0.0
(for floating point types) or NULL (for pointer types).

> Since when
> does memset() even care about integer types?

It doesn't. It's just that all-bits-zero /is/ guaranteed to be 0 for integer
types.

>>> In most calloc()
>>> implementations I've seen, they're just malloc() + memset().
>>
>> And that's why. All calloc gives you is a block of memory with
>> all-bits-zero (for which memset is a fairly reasonable implementation
>> technique). But all-bits-zero doesn't necessarily mean "zero value", for
>> pointer types and floating point types.
>
> Alright, and on that token, since we're getting fairly ridiculous by now -
> how would all-bits-zero on said (funky machines) guarantee integer zero?

Because the Standard requires it. This has long been established for char,
and the Committee, when asked to confirm or deny that it applied to all
integer types, confirmed that it does. So any conforming implementation
must get this right, even if it means doing bitty-box magic under the hood.

Christopher Layne

unread,
Oct 3, 2006, 2:53:44 PM10/3/06
to
Richard Heathfield wrote:
>[defensive programming yadda yadda]

I meant it is *implied* and was not written because it wasn't relevant to the
discussion at hand.

> Because the Standard requires it. This has long been established for char,
> and the Committee, when asked to confirm or deny that it applied to all
> integer types, confirmed that it does. So any conforming implementation
> must get this right, even if it means doing bitty-box magic under the hood.

You clipped my last segment.

If a machine expressed integer 0 as all 1 bits internally, and I called
memset(&object, 0, sizeof(object)); that's going to result in object set to
all 0 bits?

Richard Heathfield

unread,
Oct 3, 2006, 3:00:42 PM10/3/06
to
Christopher Layne said:

> Richard Heathfield wrote:
>>[defensive programming yadda yadda]
>
> I meant it is *implied* and was not written because it wasn't relevant to
> the discussion at hand.

I understood what you meant by "implied", and my previous answer to that
point remains valid IMHO.

> You clipped my last segment.

Oops.

> If a machine expressed integer 0 as all 1 bits internally, and I called
> memset(&object, 0, sizeof(object)); that's going to result in object set
> to all 0 bits?

Yes, it must. The machine's bizarre internal representation does not excuse
the implementation from its obligations. The semantics of memset(&object,
0, sizeof(object)) is "starting at the address indicated by object, set
sizeof(object) bytes to the value (unsigned char)0". If object has integer
type then that process must have the effect of setting object's value to 0.
If it has some other type, however, there is no such requirement.

Yevgen Muntyan

unread,
Oct 3, 2006, 3:53:58 PM10/3/06
to
Richard Heathfield wrote:
> Christopher Layne said:
>
>
>>Richard Heathfield wrote:
>>
>>>[defensive programming yadda yadda]
>>
>>I meant it is *implied* and was not written because it wasn't relevant to
>>the discussion at hand.
>
>
> I understood what you meant by "implied", and my previous answer to that
> point remains valid IMHO.
>
>
>>You clipped my last segment.
>
>
> Oops.
>
>
>>If a machine expressed integer 0 as all 1 bits internally, and I called
>>memset(&object, 0, sizeof(object)); that's going to result in object set
>>to all 0 bits?
>
>
> Yes, it must. The machine's bizarre internal representation does not excuse
> the implementation from its obligations. The semantics of memset(&object,
> 0, sizeof(object)) is "starting at the address indicated by object, set
> sizeof(object) bytes to the value (unsigned char)0". If object has integer
> type then that process must have the effect of setting object's value to 0.
> If it has some other type, however, there is no such requirement.

Standard says in 7.20.3.1: "The calloc function allocates space for an
array of nmemb objects, each of whose size
is size. The space is initialized to all bits zero."
It looks like "starting at the address indicated by object, set
> sizeof(object) bytes to the value (unsigned char)0" is your own
interpretation caused by the knowledge of real world computers and
compilers :)

Anyway, this newsgroup is not comp.std.c is it? So you are playing
games with standard here; you are saying "On some machines, that isn't


the case. If you are excluding such machines, you are in the wrong

newsgroup.", and it's no good. Show me chunk of real world code
which will work on any machine covered by standard; or stop pretending
C doesn't mean a programming language used in real world.

The question was specifically about existence of machines with certain
properties, for a real world application, not about whether standard
says yes or no about some particular thing.

Regards,
Yevgen

Christopher Layne

unread,
Oct 3, 2006, 4:12:15 PM10/3/06
to
Yevgen Muntyan wrote:

> The question was specifically about existence of machines with certain
> properties, for a real world application, not about whether standard
> says yes or no about some particular thing.
>
> Regards,
> Yevgen

Then set your structure members to NULL and get on with life already. It's not
that hard :)

Keith Thompson

unread,
Oct 3, 2006, 4:15:10 PM10/3/06
to
Richard Heathfield <inv...@invalid.invalid> writes:
> [much snippage]
> Yevgen Muntyan said:
[...]

>> C standard guarantees that NULL == (void*) 0, doesn't it
>
> No, it guarantees that NULL expands to an implementation-defined null
> pointer constant. Since (void *) 0 is indeed an implementation-defined null
> pointer constant, it will always compare equal with NULL, but NULL may be
> defined as, say, 0.

By "No", did you mean "Yes"? As you say, the standard does guarantee
that NULL == (void*) 0, assuming that "==" means "==" and not "is
defined as".

Keith Thompson

unread,
Oct 3, 2006, 4:22:44 PM10/3/06
to
Richard Heathfield <inv...@invalid.invalid> writes:
> Christopher Layne said:
[...]

>> If a machine expressed integer 0 as all 1 bits internally, and I called
>> memset(&object, 0, sizeof(object)); that's going to result in object set
>> to all 0 bits?
>
> Yes, it must. The machine's bizarre internal representation does not excuse
> the implementation from its obligations. The semantics of memset(&object,
> 0, sizeof(object)) is "starting at the address indicated by object, set
> sizeof(object) bytes to the value (unsigned char)0". If object has integer
> type then that process must have the effect of setting object's value to 0.
> If it has some other type, however, there is no such requirement.

As far as I know, the C90 standard doesn't explicitly guarantee that
all-bits-zero is a representation of 0 for integer types. The C99
standard doesn't either (if there are padding bits, all-bits-zero
could be a trap representation) -- but one of the later Technical
Corrigenda added the guarantee. In n1124, 6.2.6.2p5 says:

For any integer type, the object representation where all the bits
are zero shall be a representation of the value zero in that type.

As far as I know, no existing C implementation has ever failed to meet
this requirement even before it was imposed, and now that it's
effectively in the standard it should be safe to assume that all
implementations meet it.

Michael Mair

unread,
Oct 3, 2006, 4:25:45 PM10/3/06
to

No, unsigned char is _guaranteed_ to have no padding bits. In addition,
it is an unsigned integer type, so the representation of
(unsigned char)0 indeed is "one byte with all bits 0".
So, Richard described it equivalently using his knowledge of the
standard.
No undue "real world" knowledge required to arrive at that one.


> Anyway, this newsgroup is not comp.std.c is it?

You clearly did not bother to do your "homework", i.e. finding out
what this newsgroup considers topical. I suggest reading
http://clc-wiki.net/wiki/intro_to_clc
and especially
http://clc-wiki.net/wiki/C_community:comp.lang.c:Introduction#topical

> So you are playing
> games with standard here; you are saying "On some machines, that isn't
> the case. If you are excluding such machines, you are in the wrong
> newsgroup.", and it's no good. Show me chunk of real world code
> which will work on any machine covered by standard; or stop pretending
> C doesn't mean a programming language used in real world.

Once again: Richard's position is correct for comp.lang.c -- apart
from that, and back to your original question:
- whenever I find some calloc() in someone's code, I assume that
the originator of this calloc() is clueless -- my personal
experience points to this relationship.
- I prefer the "constructor" or "init element" methods for setting
up struct types that may vary during development.
- The compiler may well optimise a malloc() call followed by a
check for NULL followed by an initialisation to effectively all
bits zero by a call to calloc() if deemed necessary.
- In addition, I often have entries that need not be initialised
to zero -- why have the overhead of calloc() to set the respective
bytes to all bits zero?

Apart from that: It is possible to write real world programmes that
run on "virtually all" hosted implementations -- implementation limits
may make the programme fail consistently, though.
In addition, one usually strives to keep the portable part of other
programmes as large as possible and isolate non-portable parts in
a couple of headers and/or modules.


> The question was specifically about existence of machines with certain
> properties, for a real world application, not about whether standard
> says yes or no about some particular thing.

There are _many_ past threads enumerating machines with null pointers
being not all bits zero. Whether you consider these machines relevant
is your decision. However, your position reads to me "I am making
non-portable assumptions but I think these are not too restrictive
and quite portable for what I want to do -- please confirm this".
Without giving us _all_ the data for a well-founded expert placet to
this. The only possible answer can be "it is not portable, so this
practice is ill-advised".


Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.

Richard Heathfield

unread,
Oct 3, 2006, 4:41:32 PM10/3/06
to
Yevgen Muntyan said:

> Richard Heathfield wrote:
>> Christopher Layne said:
>>
>>>If a machine expressed integer 0 as all 1 bits internally, and I called
>>>memset(&object, 0, sizeof(object)); that's going to result in object set
>>>to all 0 bits?
>>
>>
>> Yes, it must. The machine's bizarre internal representation does not
>> excuse the implementation from its obligations. The semantics of
>> memset(&object, 0, sizeof(object)) is "starting at the address indicated
>> by object, set sizeof(object) bytes to the value (unsigned char)0". If
>> object has integer type then that process must have the effect of setting
>> object's value to 0. If it has some other type, however, there is no such
>> requirement.
>
> Standard says in 7.20.3.1: "The calloc function allocates space for an
> array of nmemb objects, each of whose size
> is size. The space is initialized to all bits zero."

Right, and that is required to mean "value 0" for integer types. If the
machine doesn't use all-bits-zero for integer types, the implementation
must somehow compensate for this, to make it transparent to the C program.

> It looks like "starting at the address indicated by object, set
> > sizeof(object) bytes to the value (unsigned char)0" is your own
> interpretation caused by the knowledge of real world computers and
> compilers :)

Well, it's mere paraphrasing, that's all. The quote marks were not intended
to suggest it was a quote from the Standard, but I apologise if anyone was
misled by that. Also, btw, I should have said "address indicated by
&object", of course.

> Anyway, this newsgroup is not comp.std.c is it? So you are playing
> games with standard here;

No, it isn't, but no, I'm not. The comp.std.c newsgroup discusses proposed
changes to the Standard, and often hosts protracted discussions on the
meaning of the Standard. Here, that is not in doubt.

> you are saying "On some machines, that isn't
> the case. If you are excluding such machines, you are in the wrong
> newsgroup.",

Right.

> and it's no good. Show me chunk of real world code
> which will work on any machine covered by standard;

No problem. Here's Stirling's Approximation:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char **argv)
{
unsigned long N = (argc > 1 ? strtoul(argv[1], NULL, 10) : 42);
double n = N > 0 ? N : 1;
double n2 = n * n;
double n3 = n2 * n;
double n4 = n2 * n2;
double e = exp(1);
double pi = atan(1) * 4;
double f1 = sqrt(2 * pi * n);
double f2 = pow(n / e, n);
double t1 = 1;
double t2 = 1 / (12 * n);
double t3 = 1 / (288 * n2);
double t4 = 139 / (51840.0 * n3);
double t5 = 571 / (2488320.0 * n4);
double f3 = t1 + t2 + t3 - t4 - t5;
double nbang = f1 * f2 * f3;
printf("%lu! = %.0f\n", N, nbang);

return 0;
}

That example was chosen at random from my codebase. If that's too trivial
for you, here's part of a (100% ISO C) program, also chosen at random, for
generating crossfades between bitmaps which will eventually end up as
animated GIFs:

#include "clc.h"
#include "clcgfx.h"
#include <stdio.h>
#include <stdlib.h>

#define REDUCE_COLOURS 0x01

int crossfade(unsigned long ximages,
const char *outpattern,
int keyframecount,
char **keyframe)
{
int ok = 0;
clc_fbuf **key = clc_malloc(keyframecount * sizeof *key);
if(key != NULL)
{
int i;
ok = 1;
for(i = 0; i < keyframecount; i++)
{
key[i] = clc_fbuf_load_bmp(keyframe[i]);
if(key[i] == NULL)
{
fprintf(stderr, "keyframe %d failed to load\n", i);
ok = 0;
}
}
}
else
{
fprintf(stderr,
"malloc failure: %lu bytes\n",
(unsigned long)(keyframecount * sizeof *key));
}
if(ok)
{
int framenumber = 0;
int k = 0;

size_t h = key[0]->height;
size_t w = key[0]->width;
char outfilename[FILENAME_MAX + 1] = {0};
clc_fbuf *outbuf = clc_fbuf_create(w, h, CLC_GFX_COLOUR_WHITE, 0, 0);

for(k = 0; outbuf != NULL && k < keyframecount; k++)
{
size_t x = 0;
size_t y = 0;
unsigned long Acolour = 0;
unsigned long Ar = 0;
unsigned long Ag = 0;
unsigned long Ab = 0;
unsigned long Bcolour = 0;
unsigned long Br = 0;
unsigned long Bg = 0;
unsigned long Bb = 0;
unsigned long Ccolour = 0;
unsigned long Cr = 0;
unsigned long Cg = 0;
unsigned long Cb = 0;

int AFrame = k;
int BFrame = (k + 1) % keyframecount;

int BFrame = (k + 1) % keyframecount;
unsigned long tween = 0;

fprintf(stderr, "Processing key frame %d\n", k);

for(tween = 0; tween < ximages; tween++)
{
double Alpha = ximages - tween;
double Beta = 0.0;
Alpha /= ximages;
Beta = 1.0 - Alpha;

fprintf(stderr, "Processing tween frame %lu\n", tween);

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
Acolour = clc_fbuf_getpixel(key[AFrame], x, y);
Bcolour = clc_fbuf_getpixel(key[BFrame], x, y);
Ar = CLC_GFX_GET_RED(Acolour);
Ag = CLC_GFX_GET_GREEN(Acolour);
Ab = CLC_GFX_GET_BLUE(Acolour);
Br = CLC_GFX_GET_RED(Bcolour);
Bg = CLC_GFX_GET_GREEN(Bcolour);
Bb = CLC_GFX_GET_BLUE(Bcolour);
Cr = (((unsigned long)((Ar * Alpha) + Br * Beta)) & 0xFF) |
REDUCE_COLOURS;
Cg = (((unsigned long)((Ag * Alpha) + Bg * Beta)) & 0xFF) |
REDUCE_COLOURS;
Cb = (((unsigned long)((Ab * Alpha) + Bb * Beta)) & 0xFF) |
REDUCE_COLOURS;
Ccolour = (Cr << 16) | (Cg << 8) | Cb;
clc_fbuf_setpixel(outbuf, x, y, Ccolour);
}
}
sprintf(outfilename, "%s%04d.bmp", outpattern, framenumber++);
clc_fbuf_save_as_bmp(outfilename, outbuf);
}
}
clc_fbuf_destroy(&outbuf);
}
else
{
fprintf(stderr, "Not enough memory - sorry.\n");
}
if(key != NULL)
{
int i;
for(i = 0; i < keyframecount; i++)
{
clc_fbuf_destroy(&key[i]);
}
clc_free(key);
}
return 0;
}

You can run that program (of which the above is a part) on a PDP, a
Window-box, a mainframe, a Linux machine, a Sparc, an Apple, an Atari ST or
an Amiga, and still get the correct outputs, given the right inputs.


> or stop pretending
> C doesn't mean a programming language used in real world.

Oh, I use it in the real world all the time. That's why I'm so careful with
it.

> The question was specifically about existence of machines with certain
> properties,

The original question about whether such machines exist was answered years
ago, in the FAQ, as I pointed out earlier. And in my subsequent replies
I've been discussing the behaviour that implementations are required to
provide for correct programs. As far as I can tell, my responses have been
appropriate to the newsgroup, the topic of discussion, the original
question, and the followup questions.

> for a real world application, not about whether standard
> says yes or no about some particular thing.

The Standard is all about real world applications. We write portable code
for hard-headed practical reasons.

Frederick Gotham

unread,
Oct 3, 2006, 4:41:39 PM10/3/06
to
Keith Thompson posted:

> As far as I know, the C90 standard doesn't explicitly guarantee that
> all-bits-zero is a representation of 0 for integer types.

Are you talking about object representation, or value representation?

If talking about object representation, then I agree.

However, if you're talking about value representation, I think that we can
make such an assumption based on other parts of the Standard (laws of
mathematics/physics and all that...). For instance, the following shall
produce all-bits-zero for an unsigned int:

1U << IMAX_BITS((unsigned)-1)-1 << 1;

At the same time, it's also guaranteed to yield the value zero.

Put them both together and it would seem that all-bits-zero must be a valid
value representation for an unsigned int. (Although I get the feeling I'm
stating the obvious...)

--

Frederick Gotham

Keith Thompson

unread,
Oct 3, 2006, 4:45:48 PM10/3/06
to
Someone <ma...@unknown.net> writes:
> Keith Thompson wrote:
>> Yevgen Muntyan <muntyan.r...@tamu.edu> writes:
>>>Keith Thompson wrote:

[...]

>>>so you can do


>>>
>>>unsigned ch = get_it_somehow();
>>>if (' ' <= ch && ch <= '~')
>>> do_something();
>> That's what isprint() is for.
>
> No it's not. isprint() is locale dependent, it's not for detecting
> printable ASCII characters (or printable UTF8 1-byte characters,
> to make it funnier, C doesn't give UTF8). There's isascii() though (not
> standard, is it?), so you really can use only issomething() C calls;
> e.g. isascii(ch) && islower(ch) detects lowercase letter.
>
> Question: what does it buy except *false* feeling of safety with
> regard to portability (false because used library is not portable)?

Yes, isprint() is locale dependent. Do you not have control over the
locale in which your program runs? You can always call setlocale().

If you prefer a non-portable solution, that's fine, as long as you're
aware that it's non-portable. But if you want advice about
non-portable solutions, this isn't the place to get it.

[...]

>>>>You might consider something like:
>>>>
>>>>#if CHAR_BIT != 8
>>>>#error CHAR_BIT != 8
>>>>#endif
>>>
>>>And I wouldn't be able to test it without screwing up or faking system
>>>headers if I were so serious to insert this useless build error :)
>>>
>>>And how is code that doesn't build better than code that builds (would
>>>be real strange if it did) and doesn't work, given that there's a list
>>>of supported platforms all of which have 8-bits bytes? At least buggy
>>>behavior would show that it indeed builds but doesn't work.
>> I like to catch errors as early as possible. If you'd rather waste
>> your time tracking down run-time bugs, that's up to you.
>
> Nah, don't generalize.

Why on Earth not?

> Imagine that some user bought a brand new
> 64-bits-per-byte machine in year 2045, and tries to compile your code.
> What would be more useful: confirmation that your code is broken (and
> you *must* assume that even if you are trying to always write super
> portable code) or useless report "it doesn't build"?

I honestly don't understand your point. What's useless about it?

If you prefer, try this:

#if CHAR_BIT != 8
#error "This code assumes CHAR_BIT == 8 (see the foobar module)"
#endif

It's about detecting errors as early as possible. If you have the
above in your code, and I try to build it on a CHAR_BIT==64 system, it
fails immediately; I can either give up, or try to modify the code so
it works on my system.

What alternative are you suggesting, and how is it better than #error?

> How exactly that #error thing catches bugs? How #error can ever help
> anything but preventing useless bugs reports (if they are useless,
> in this case they would be useful).

You keep using the word "useless". It's not helping to communicate
what you mean.

Frederick Gotham

unread,
Oct 3, 2006, 4:46:52 PM10/3/06
to
Richard Heathfield posted:

<snip>


> double n = N > 0 ? N : 1;
> double n2 = n * n;
> double n3 = n2 * n;
> double n4 = n2 * n2;
> double e = exp(1);
> double pi = atan(1) * 4;
> double f1 = sqrt(2 * pi * n);
> double f2 = pow(n / e, n);
> double t1 = 1;
> double t2 = 1 / (12 * n);
> double t3 = 1 / (288 * n2);
> double t4 = 139 / (51840.0 * n3);
> double t5 = 571 / (2488320.0 * n4);
> double f3 = t1 + t2 + t3 - t4 - t5;
> double nbang = f1 * f2 * f3;

<snip>


> size_t x = 0;
> size_t y = 0;
> unsigned long Acolour = 0;
> unsigned long Ar = 0;
> unsigned long Ag = 0;
> unsigned long Ab = 0;
> unsigned long Bcolour = 0;
> unsigned long Br = 0;
> unsigned long Bg = 0;
> unsigned long Bb = 0;
> unsigned long Ccolour = 0;
> unsigned long Cr = 0;
> unsigned long Cg = 0;
> unsigned long Cb = 0;


I would have thought you'd find it more convenient to use "multiple
definitions" rather than repeating the type name:

long unsigned a,b,c,d,e,f,g...

--

Frederick Gotham

Keith Thompson

unread,
Oct 3, 2006, 4:47:40 PM10/3/06
to

("ghetto?")

You can assign structures; there's no need to use memcpy().

If the global object is const, as I defined it above, there's no real
problem with making it global.

Richard Heathfield

unread,
Oct 3, 2006, 4:55:46 PM10/3/06
to
Keith Thompson said:

> Richard Heathfield <inv...@invalid.invalid> writes:
>> [much snippage]
>> Yevgen Muntyan said:
> [...]
>>> C standard guarantees that NULL == (void*) 0, doesn't it
>>
>> No, it guarantees that NULL expands to an implementation-defined null
>> pointer constant. Since (void *) 0 is indeed an implementation-defined
>> null pointer constant, it will always compare equal with NULL, but NULL
>> may be defined as, say, 0.
>
> By "No", did you mean "Yes"? As you say, the standard does guarantee
> that NULL == (void*) 0, assuming that "==" means "==" and not "is
> defined as".

Yeah, okay, I probably over-reacted there - I was just trying to make it
absolutely clear that the Standard does not mandate that NULL must be
#defined as (void *) 0 - because of course it doesn't.

Richard Heathfield

unread,
Oct 3, 2006, 4:59:56 PM10/3/06
to
Keith Thompson said:

<snip>



> As far as I know, the C90 standard doesn't explicitly guarantee that
> all-bits-zero is a representation of 0 for integer types.

Yeah, we used to raise this all the time. Some years ago, though, ISO got
sick of being hassled about it and said something along the lines of "yes,
yes, YES already! We guarantee it! Now be gone, and stop giving headache
all of time. Where did I leave that beer?".

Ask in comp.std.c for details. :-)

Richard Heathfield

unread,
Oct 3, 2006, 5:07:47 PM10/3/06
to
Frederick Gotham said:

> I would have thought

You can start by thinking about apologising to Keith for behaving abusively
and libellously towards him in this newsgroup.

Until you're ready to rejoin civilisation, I'm not ready to bother
discussing your misunderstandings about my style choices.

Christopher Layne

unread,
Oct 3, 2006, 5:09:58 PM10/3/06
to
Richard Heathfield wrote:

> You can start by thinking about apologising to Keith for behaving abusively
> and libellously towards him in this newsgroup.
>
> Until you're ready to rejoin civilisation, I'm not ready to bother
> discussing your misunderstandings about my style choices.

Haha. Like old grandmothers sometimes.

Richard Heathfield

unread,
Oct 3, 2006, 5:23:19 PM10/3/06
to
Christopher Layne said:

When someone accuses *you* of being associated with the political group
responsible for the murder of ten million people in death camps in the
1930s and 1940s, I hope you will have the courage to defend yourself
stalwartly against such an attack, and will not be too upset when foolish
people mock you for doing so.

Yevgen Muntyan

unread,
Oct 3, 2006, 5:09:29 PM10/3/06
to

Indeed, I was tricked by that wording and inferred that his words imply
that Standard guarantees that

int *a;
int i;
char c = 0;
for (i = 0; i < sizeof (a); ++i)
memcpy (((char*)&a) + i, &c, 1);

is equivalent to

int *a;
memset (&a, 0, sizeof (a))

(or analogous thing with calloc()). What Richard said was indeed
"butter is made of butter", since standard says "all zero bits",
and it says the same about (char)0, and there is no way you can
actually *set* all *bytes* in a structure to (unsigned char)0. (To
that effect you can use memset, memcpy and so on, but does standard
say what it means "to set bytes to zero"?)

>> Anyway, this newsgroup is not comp.std.c is it?
>
>
> You clearly did not bother to do your "homework", i.e. finding out
> what this newsgroup considers topical. I suggest reading
> http://clc-wiki.net/wiki/intro_to_clc
> and especially
> http://clc-wiki.net/wiki/C_community:comp.lang.c:Introduction#topical

Indeed, that says "The group deals with C only to the (narrow) extent
that the ANSI/ISO C Standard defines it.", so my question was off-topic
since I did know standard doesn't guarantee all-zero-bits NULL.

So, when I want to get some knowledge of C programmers out there,
comp.lang.c is a wrong place.

>> So you are playing
>> games with standard here; you are saying "On some machines, that isn't
>> the case. If you are excluding such machines, you are in the wrong
>> newsgroup.", and it's no good. Show me chunk of real world code
>> which will work on any machine covered by standard; or stop pretending
>> C doesn't mean a programming language used in real world.
>
>
> Once again: Richard's position is correct for comp.lang.c -- apart
> from that, and back to your original question:
> - whenever I find some calloc() in someone's code, I assume that
> the originator of this calloc() is clueless -- my personal
> experience points to this relationship.

Single fact that zeroing memory gives you a crash instead of random
behavior very well justifies using of calloc(), unless it's expensive
(or is there any other objection to using calloc()?).

> - I prefer the "constructor" or "init element" methods for setting
> up struct types that may vary during development.

I have init() methods, but they do not allocate memory, that's done
elsewhere, and I get calloc'ed structures, and so on and so forth.
Blah blah blah.
And then in my something_new() methods I like to use calloc() (actually
a wrapper around calloc which will abort if calloc() fails).

> - The compiler may well optimise a malloc() call followed by a
> check for NULL followed by an initialisation to effectively all
> bits zero by a call to calloc() if deemed necessary.

Again, calloc call happens elsewhere, compiler has no idea about that.
And mind you, "optimise"? Holy standard knows that word? Or you just
using off-topic arguments since conversation is off-topic anyway?

> - In addition, I often have entries that need not be initialised
> to zero -- why have the overhead of calloc() to set the respective
> bytes to all bits zero?

Overhead is how much exactly? A very simple example: when I need to
scroll in a text widget, I create a structure with some stuff inside,
like what line to scroll to and so on. "Overhead" is exactly zero.

> Apart from that: It is possible to write real world programmes that
> run on "virtually all" hosted implementations -- implementation limits
> may make the programme fail consistently, though.
> In addition, one usually strives to keep the portable part of other
> programmes as large as possible and isolate non-portable parts in
> a couple of headers and/or modules.

Yes, but as I said elsewhere, I am not going not to assume 8 bits
in bytes whenever it's convenient (X likes 8 bits bytes, and there
are cases where you use 8, 16, or 32 as an argument. guess what 8 is).
Of course convenience should not hurt portability. Assuming 8-bits byte
doesn't.

>> The question was specifically about existence of machines with certain
>> properties, for a real world application, not about whether standard
>> says yes or no about some particular thing.
>
>
> There are _many_ past threads enumerating machines with null pointers
> being not all bits zero. Whether you consider these machines relevant
> is your decision. However, your position reads to me "I am making
> non-portable assumptions but I think these are not too restrictive
> and quite portable for what I want to do -- please confirm this".

Care to read the original question? Very simple. Yes, I did use words
like "do I care", sorry for that, next time I will try to use more
robot language.

> Without giving us _all_ the data for a well-founded expert placet to
> this. The only possible answer can be "it is not portable, so this
> practice is ill-advised".

Well, if you really are willing to help and need _all_ the data, you
could for start simply tell if there's a machine with X with NULL not
being all zero bits; as far as I understand there's none.
Come on, you care about absolute portability, great. But why tell all
this great stuff about this and that when the question was indeed
simple (I actually thought that there is a strange platform with X
where NULL might not be all zero bits, sorry for not admitting my
stupidity and asking you to forgive me at the very beginning)?

Regards,
Yevgen

Christopher Layne

unread,
Oct 3, 2006, 5:34:49 PM10/3/06
to
Richard Heathfield wrote:
> When someone accuses *you* of being associated with the political group
> responsible for the murder of ten million people in death camps in the
> 1930s and 1940s, I hope you will have the courage to defend yourself
> stalwartly against such an attack, and will not be too upset when foolish
> people mock you for doing so.

If someone were to say I were a Nazi, I'd file it under every other usenet
thread which degenerated into "You must be a Nazi then" and laugh it off as
stupidity.

Christopher Layne

unread,
Oct 3, 2006, 5:37:28 PM10/3/06
to
Richard Heathfield wrote:
> When someone accuses *you* of being associated with the political group
> responsible for the murder of ten million people in death camps in the
> 1930s and 1940s, I hope you will have the courage to defend yourself
> stalwartly against such an attack, and will not be too upset when foolish
> people mock you for doing so.

Also, you're taking more years off your life getting upset and worrying about
this type of stuff than they are taking off of theirs. Who ends up being the
loser there? Seriously, don't sweat so much of it.

Frederick Gotham

unread,
Oct 3, 2006, 5:44:30 PM10/3/06
to
Richard Heathfield posted:

> When someone accuses *you* of being associated with the political group
> responsible for the murder of ten million people in death camps in the
> 1930s and 1940s, I hope you will have the courage to defend yourself
> stalwartly against such an attack, and will not be too upset when foolish
> people mock you for doing so.

OK here's where I'm confused. When did I ever indicate that anyone had any
association with a political group, murderers, etc.?

I used the word, "fascist", to indicate a philosophy of complete power,
forcibly suppressing opposition and criticism.

I condemned Keith's reaction to my usage of "char unsigned". Keith, rather
than simply acknowledging that it was perfectly legal alternative syntax,
berrated me for using it and even went so far as to rudely label my methods
as "perverse" to a new-comer before I even got a chance to engage in first
contact with said new-comer. I also condemn the way in which he expressed his
opinion with regard to "C==v Vs v==C"; he labelled the alternative way of
doing it as "unbearably ugly". I see a pattern of "My way is the only way of
doing things, everything else is crap -- do it my way". That's why the word,
"fascist", came to mind. It had nothing to do with politics, murder, etc..

--

Frederick Gotham

Richard Heathfield

unread,
Oct 3, 2006, 5:55:15 PM10/3/06
to
Christopher Layne said:

Yeah, Godwin's Law and all that. Nevertheless, I am confident that Mr
Gotham's stupidity is merely temporary, and in due course he'll realise
that being a pariah isn't doing him any good, at which point - presumably -
he will apologise for his abusive attack on Keith Thompson.

[and, in another reply, said]

> Also, you're taking more years off your life getting upset

I'm not upset, and I'm not worrying. Any parent is perfectly capable of
handling this kind of situation without so much as a blip in blood
pressure.

> and
> worrying about this type of stuff than they are taking off of
> theirs. Who ends up being the loser there?

Mr Gotham has ended up being the loser on several occasions so far, where he
has asked questions and received no answers.

> Seriously, don't sweat so much of it.

I'm not sweating. (Actually, I am, but not for that reason. I've got a nasty
dose of flu at the moment.) But up until now, comp.lang.c has always been a
fairly civilised place, with people treating each other with respect, and
having the good grace to apologise when they make mistakes - and yet Mr
Gotham thinks that he can be as rude as he likes to anyone he likes, with
no consequences at all, and that anyone who complains is just making a
silly fuss. I think this newsgroup will be a poorer place if people start
behaving like that, don't you?

Yevgen Muntyan

unread,
Oct 3, 2006, 5:34:38 PM10/3/06
to
Keith Thompson wrote:

> Someone <ma...@unknown.net> writes:
>
>>Keith Thompson wrote:
>>
>>>Yevgen Muntyan <muntyan.r...@tamu.edu> writes:
>>>
>>>>Keith Thompson wrote:
>
>
> [...]
>
>
>>>>so you can do
>>>>
>>>>unsigned ch = get_it_somehow();
>>>>if (' ' <= ch && ch <= '~')
>>>> do_something();
>>>
>>>That's what isprint() is for.
>>
>>No it's not. isprint() is locale dependent, it's not for detecting
>>printable ASCII characters (or printable UTF8 1-byte characters,
>>to make it funnier, C doesn't give UTF8). There's isascii() though (not
>>standard, is it?), so you really can use only issomething() C calls;
>>e.g. isascii(ch) && islower(ch) detects lowercase letter.
>>
>>Question: what does it buy except *false* feeling of safety with
>>regard to portability (false because used library is not portable)?
>
>
> Yes, isprint() is locale dependent. Do you not have control over the
> locale in which your program runs? You can always call setlocale().

Well, calling setlocale to make islower to recognize only ascii while
you can use arithmetics might be conforming to standard but is really
strange, even if you don't consider multi-threaded setup.

> If you prefer a non-portable solution, that's fine, as long as you're
> aware that it's non-portable.

Yep.

[snip]

>> Imagine that some user bought a brand new
>>64-bits-per-byte machine in year 2045, and tries to compile your code.
>>What would be more useful: confirmation that your code is broken (and
>>you *must* assume that even if you are trying to always write super
>>portable code) or useless report "it doesn't build"?
>
>
> I honestly don't understand your point. What's useless about it?
>
> If you prefer, try this:
>
> #if CHAR_BIT != 8
> #error "This code assumes CHAR_BIT == 8 (see the foobar module)"
> #endif
>
> It's about detecting errors as early as possible. If you have the
> above in your code, and I try to build it on a CHAR_BIT==64 system, it
> fails immediately; I can either give up, or try to modify the code so
> it works on my system.
>
> What alternative are you suggesting, and how is it better than #error?

My alternative is not to do that so one can actually try the code
on brand-new MegaPC-2045.

If you are talking about closed-source stuff, where you are the only
person (or a member of a single group, or whatever) who compiles the
code, then of course you want immediate build error. And then we are
talking about different things :)

My setup is like this: I have PC's with linux, FreeBSD, and windows, and
I occasionally use other systems/architectures. It doesn't happen often
since I don't have those systems/architectures, so user bug reports are
very valuable. And I don't expect I will try MegaPC-2045 before users,
they usually have better hardware than I do.

>>How exactly that #error thing catches bugs? How #error can ever help
>>anything but preventing useless bugs reports (if they are useless,
>>in this case they would be useful).
>
>
> You keep using the word "useless". It's not helping to communicate
> what you mean.

Useless for me, to be exact, yes.

Regards,
Yevgen

Yevgen Muntyan

unread,
Oct 3, 2006, 5:51:32 PM10/3/06
to
Richard Heathfield wrote:

[code]

I admit, it was stupid. There are really programs that can read files,
write to files, and process some data, and not depend on any OS-specific
services, nor on libraries other than C library.

Anyway, I believe I understood what my mistakes here are, and what
and why. But, see below.

> The original question about whether such machines exist was answered years
> ago, in the FAQ, as I pointed out earlier.

I asked a bit more specific question than that answered in FAQ, and
noone actually answered it here (though I did get what I need at least)
;)

> And in my subsequent replies
> I've been discussing the behaviour that implementations are required to
> provide for correct programs. As far as I can tell, my responses have been
> appropriate to the newsgroup, the topic of discussion, the original
> question, and the followup questions.

No, your replies (while indeed useful, I didn't know about zero bits in
integer 0) were not on the topic of discussion. The discussion started
with a very simple question, and *then* it grew up into usual
bad-or-good stuff.

>>for a real world application, not about whether standard
>>says yes or no about some particular thing.
>
>
> The Standard is all about real world applications.

Yeah, just not about all applications ;)

Thank you,
Yevgen

Richard Heathfield

unread,
Oct 3, 2006, 6:06:31 PM10/3/06
to
Yevgen Muntyan said:

> Michael Mair wrote:
>>
>> No, unsigned char is _guaranteed_ to have no padding bits. In addition,
>> it is an unsigned integer type, so the representation of
>> (unsigned char)0 indeed is "one byte with all bits 0".
>> So, Richard described it equivalently using his knowledge of the
>> standard.
>
> Indeed, I was tricked by that wording

I apologise for that. Again.

> and inferred that his words imply
> that Standard guarantees that
>
> int *a;
> int i;
> char c = 0;
> for (i = 0; i < sizeof (a); ++i)
> memcpy (((char*)&a) + i, &c, 1);
>
> is equivalent to
>
> int *a;
> memset (&a, 0, sizeof (a))

The Standard does indeed guarantee that.

> (or analogous thing with calloc()). What Richard said was indeed
> "butter is made of butter", since standard says "all zero bits",
> and it says the same about (char)0, and there is no way you can
> actually *set* all *bytes* in a structure to (unsigned char)0.

Oh yes there is.

unsigned char *p = (unsigned char *)&mystruct;
size_t len = sizeof mystruct;
while(len--)
{
*p++ = 0;
}

> (To
> that effect you can use memset, memcpy and so on, but does standard
> say what it means "to set bytes to zero"?)

It doesn't have to, because it doesn't mention zero in the descriptions of
memset and memcpy.

4.11.2.1 The memcpy function

Synopsis

#include <string.h>
void *memcpy(void *s1, const void *s2, size_t n);

Description

The memcpy function copies n characters from the object pointed to
by s2 into the object pointed to by s1 . If copying takes place
between objects that overlap, the behavior is undefined.

Returns

The memcpy function returns the value of s1 .

4.11.6.1 The memset function

Synopsis

#include <string.h>
void *memset(void *s, int c, size_t n);

Description

The memset function copies the value of c (converted to an unsigned
char ) into each of the first n characters of the object pointed to by
s .

Returns

The memset function returns the value of s .


> So, when I want to get some knowledge of C programmers out there,
> comp.lang.c is a wrong place.

Do you think you've been poorly served by the answers given here?


> Single fact that zeroing memory gives you a crash instead of random
> behavior very well justifies using of calloc(),

But that is not a fact, merely an observation of the behaviour of a limited
number of systems, and by no mean a universal fact. No, the advantage of
zeroing memory is only this - that it allows you a fast, convenient way to
initialise dynamic arrays of integer types.

> unless it's expensive
> (or is there any other objection to using calloc()?).

Only that it's pointless, except in the case of arrays of integer types.

<snip>

Keith Thompson

unread,
Oct 3, 2006, 6:13:54 PM10/3/06
to
Frederick Gotham <fgot...@SPAM.com> writes:
> Keith Thompson posted:
>> As far as I know, the C90 standard doesn't explicitly guarantee that
>> all-bits-zero is a representation of 0 for integer types.
>
> Are you talking about object representation, or value representation?
[snip]

I'm not talking *to you* about anything.

Apologize.

Richard Heathfield

unread,
Oct 3, 2006, 6:28:02 PM10/3/06
to
Frederick Gotham said:

> Richard Heathfield posted:
>
>> When someone accuses *you* of being associated with the political group
>> responsible for the murder of ten million people in death camps in the
>> 1930s and 1940s, I hope you will have the courage to defend yourself
>> stalwartly against such an attack, and will not be too upset when foolish
>> people mock you for doing so.
>
> OK here's where I'm confused. When did I ever indicate that anyone had any
> association with a political group, murderers, etc.?

When you called Keith Thompson a fascist.

> I used the word, "fascist", to indicate a philosophy of complete power,
> forcibly suppressing opposition and criticism.

Yes. Do you know the name of the world's most famous fascist ever? Adolf
Hitler. When you accuse someone of being a fascist, you're aligning them
with Hitler. That isn't funny.

> I condemned Keith's reaction to my usage of "char unsigned".

Well, condemning people's reactions doesn't sound very liberal to me. Have
you ever considered that you might be just a little hypocritical here?

> Keith, rather
> than simply acknowledging that it was perfectly legal alternative syntax,
> berrated me for using it and even went so far as to rudely label my
> methods as "perverse" to a new-comer

Well, they're certainly very unorthodox, and will slow up any reader.
"Perverse" is a little strong, perhaps, but not excessively so.


> before I even got a chance to engage
> in first contact with said new-comer.

Irrelevant, I think. This is a public forum.

> I also condemn the way in which he
> expressed his opinion with regard to "C==v Vs v==C";

You're very quick to condemn. But I'm not going to draw comparisons. Oh no.
Because if I did, with whom would I compare you? There's pause for thought,
eh?


> he labelled the alternative way of doing it as "unbearably ugly".

And that is *his right*. As it happens, I disagree with him there. I think
his opinion is not particularly constructive or helpful, and I think he
underestimates the benefits of C==v. (Keith, mental note to hammer this one
out at a later date, okay?)

But - and this is important - he and I can disagree about this, and about
much else besides, and yet remain on speaking terms. I have never called
Keith Thompson a fascist, and he has never called me one. We treat each
other with respect and courtesy, all the time, but *especially* when we are
disagreeing with each other. Basically, Keith acts like a grown-up, and I
respect that. And presumably his motivation is similar in the other
direction.

If you want to be treated like a grown-up, it's time you started acting like
one. And on this occasion, that means earning some serious street cred by
having the guts to apologise.

> I see a pattern of "My
> way is the only way of doing things, everything else is crap -- do it my
> way".

Well, yes, that's programmers for you. You come across like that too, if you
only knew it. And I bet I do too. We can't help that. But if we can
recognise it in ourselves, we can understand it in others, and make
allowances for it. Yes, of course Keith thinks his methodology is a good
one. You know why? Because it *works* - for him. And mine works for me. And
no doubt yours works for you. After all, if it didn't, you'd change it,
right? But where such discussions become useful is that meeting point where
Keith says, "well, Richard, if you must do your stupid stupid foo bar baz
trick, why not frobnitz the doofle at the same time? Then you'd get better
mips through your cruftmeter - you wouldn't catch me dead doing that, but
it might work for you", and I think "gosh, what a great idea, why didn't I
think of that?" Even in diehard disagreement there can be mutual respect
and learning. Think about it.


> That's why the word, "fascist", came to mind. It had nothing to do
> with politics, murder, etc..

You don't get to choose what words mean to those who read them.

Now - are you going to do the decent thing?

This is my last such request, I promise. If you're just a bull-headed
Irishman who's damned if he'll apologise, fine, I'll just killfile you by
tomorrow morning, and then we've both lost any chance of interacting with
each other, to our mutual loss, I'm sure. But I'm hoping you're not just a
bull-headed Irishman.

Christopher Layne

unread,
Oct 3, 2006, 6:35:09 PM10/3/06
to
Richard Heathfield wrote:
>> I used the word, "fascist", to indicate a philosophy of complete power,
>> forcibly suppressing opposition and criticism.
>
> Yes. Do you know the name of the world's most famous fascist ever? Adolf
> Hitler. When you accuse someone of being a fascist, you're aligning them
> with Hitler. That isn't funny.

Sorry Richard, I'm going to have to call bullshit on this. You don't just
project that on someone for using a standard english word that's adjective in
nature. Completely not fair.

X or Y is a facist does not say X or Y is HITLER, cmon.

Richard Heathfield

unread,
Oct 3, 2006, 6:44:56 PM10/3/06
to
Yevgen Muntyan said:

> Richard Heathfield wrote:


>
>> Yevgen Muntyan said:
>>
>>>and it's no good. Show me chunk of real world code
>>>which will work on any machine covered by standard;
>>
>>
>> No problem. Here's
> [code]
>
> I admit, it was stupid. There are really programs that can read files,
> write to files, and process some data, and not depend on any OS-specific
> services, nor on libraries other than C library.

Yeah, everyone knows you can't do spit in ISO C - until someone starts to
make a list of all the things you /can/ do...

Those were just two examples taken at random, btw. Plenty more where they
came from.


>> The original question about whether such machines exist was answered
>> years ago, in the FAQ, as I pointed out earlier.
>
> I asked a bit more specific question than that answered in FAQ, and
> noone actually answered it here (though I did get what I need at least)
> ;)

Hmmm - I must have missed that, then. Sorry about that.

<snip>

>> The Standard is all about real world applications.
>
> Yeah, just not about all applications ;)

Quite so. :-)

Richard Heathfield

unread,
Oct 3, 2006, 6:55:13 PM10/3/06
to
Christopher Layne said:

> Richard Heathfield wrote:
>>> I used the word, "fascist", to indicate a philosophy of complete power,
>>> forcibly suppressing opposition and criticism.
>>
>> Yes. Do you know the name of the world's most famous fascist ever? Adolf
>> Hitler. When you accuse someone of being a fascist, you're aligning them
>> with Hitler. That isn't funny.
>
> Sorry Richard, I'm going to have to call bullshit on this. You don't just
> project that on someone for using a standard english word that's adjective
> in nature.

"Fascist (also without cap): an exponent or supporter of Fascism or
(loosely) anyone with extreme right-wing, nationalistic, etc views or
methods" - Chambers (which carries no other definition for the word).

I don't think I'm being unreasonable in claiming that, by describing Keith
as a Fascist, Mr Gotham was stating that Keith is an exponent or supporter
of Fascism or, at least, has extreme right-wing nationalistic views or
methods. Keith has every right to expect an apology for this unjust
accusation.

> Completely not fair.
>
> X or Y is a facist does not say X or Y is HITLER, cmon.

Correct, but I didn't claim that, so I don't see your point.

Frederick Gotham

unread,
Oct 3, 2006, 6:59:02 PM10/3/06
to
Richard Heathfield posted:

>> I used the word, "fascist", to indicate a philosophy of complete power,
>> forcibly suppressing opposition and criticism.
>
> Yes. Do you know the name of the world's most famous fascist ever? Adolf
> Hitler. When you accuse someone of being a fascist, you're aligning them
> with Hitler. That isn't funny.


I don't see your logic. If people had called Adolf Hitler a white wine
connoisseur, does that mean that I can't call Keith Thompson a white wine
connoisseur because I'll be "aligning him" with Hitler?

If I say something smells funny, I'm not implying that it reeks of two-
week-old decomposed carcase. When I say someone is fascist, I'm not
implying that they're fascist to the extent that Hitler was.

I quite dislike the idea that a term, phrase or symbol suddenly becomes
taboo just because someone or something was associated with it at some
time. Take the swastika for instance; should Hindus have to take down all
the swastikas in their homes simply because the Nazis decided to adopt that
symbol? I think not. Nor do I think should the word, "fascist", become
taboo simply because it was used to describe a few bad people -- it gives
Hitler far too much respect.


> Well, condemning people's reactions doesn't sound very liberal to me.
> Have you ever considered that you might be just a little hypocritical
> here?


He did not simply express his dislike of my style, he went further to
degrade me.


> And that is *his right*. As it happens, I disagree with him there. I
> think his opinion is not particularly constructive or helpful, and I
> think he underestimates the benefits of C==v. (Keith, mental note to
> hammer this one out at a later date, okay?)


The age old saying comes to mind, "It's not what you say, it's how you say
it.".

There's a difference between one painter saying that another painter's work
is unbareably ugly; and saying that the other painter's work simply isn't
their cup of tea.


> But - and this is important - he and I can disagree about this, and
> about much else besides, and yet remain on speaking terms. I have never
> called Keith Thompson a fascist, and he has never called me one. We
> treat each other with respect and courtesy, all the time, but
> *especially* when we are disagreeing with each other. Basically, Keith
> acts like a grown-up, and I respect that. And presumably his motivation
> is similar in the other direction.
>
> If you want to be treated like a grown-up, it's time you started acting
> like one. And on this occasion, that means earning some serious street
> cred by having the guts to apologise.


If I were to apologise, I'd be condoning the hostile manner in which Keith
expressed his opinion of my coding style -- and I'm not yet prepared to do
that.


>> I see a pattern of "My
>> way is the only way of doing things, everything else is crap -- do it
>> my way".
>
> Well, yes, that's programmers for you. You come across like that too, if
> you only knew it. And I bet I do too. We can't help that. But if we can
> recognise it in ourselves, we can understand it in others, and make
> allowances for it.


There are _several_ things I can think of that I hate:

(1) Not defining function parameters as const.
(2) Using i++ where ++i would suffice.
(3) Same-line-open brace for function bodies.

When I see these things, I don't stop to degrade the programmer by labeling
their ways as "just perverse ways".


> Yes, of course Keith thinks his methodology is a good one. You know why?
> Because it *works* - for him. And mine works for me. And no doubt yours
> works for you. After all, if it didn't, you'd change it, right? But
> where such discussions become useful is that meeting point where Keith
> says, "well, Richard, if you must do your stupid stupid foo bar baz
> trick, why not frobnitz the doofle at the same time? Then you'd get
> better mips through your cruftmeter - you wouldn't catch me dead doing
> that, but it might work for you", and I think "gosh, what a great idea,
> why didn't I think of that?" Even in diehard disagreement there can be
> mutual respect and learning. Think about it.


Yes, but I wasn't treated with any such respect; here's what _I_ got:

| A note to the original poster: "char unsigned" and "char signed"
| are just perverse ways of writing "unsigned char" and
| "signed char", respectively.

Does the word "just perverse ways" convey an air of, "Well you have your
own way and that works for you, and I have my own way too.", to you?




> You don't get to choose what words mean to those who read them.


Which is why I consult a dictionary from time to time, especially when the
reader speaks a different dialect of English to me. (Remember that whole
"domestic" business?)


> Now - are you going to do the decent thing?


If I do the "decent thing" -- as you say -- I will do it on my terms rather
than be bullied into it. My own stance on things is:

Keith degraded me and treated me disrespectfully, and I responded by
expressing my view that I found him to be fascist. Now I'm being hounded to
apologise as if I should have miraculously seen the error of my ways by
now.


> This is my last such request, I promise. If you're just a bull-headed
> Irishman who's damned if he'll apologise, fine, I'll just killfile you
> by tomorrow morning, and then we've both lost any chance of interacting
> with each other, to our mutual loss, I'm sure. But I'm hoping you're not
> just a bull-headed Irishman.


Is this the part where I repeatedly insist that you apologise to me for
racial profiling? Give me a few hours and I'll see if I come up with some
notorious villian who was called a "bull-headed Irishman" at some time, so
that I may accuse you of aligning me with him.

Anywho, I'm off to bed, it's hitting midnight here in Ireland. Good night,
Richard.

--

Frederick Gotham

Christopher Layne

unread,
Oct 3, 2006, 7:00:07 PM10/3/06
to
Richard Heathfield wrote:
> "Fascist (also without cap): an exponent or supporter of Fascism or
> (loosely) anyone with extreme right-wing, nationalistic, etc views or
> methods" - Chambers (which carries no other definition for the word).
>
> I don't think I'm being unreasonable in claiming that, by describing Keith
> as a Fascist, Mr Gotham was stating that Keith is an exponent or supporter
> of Fascism or, at least, has extreme right-wing nationalistic views or
> methods. Keith has every right to expect an apology for this unjust
> accusation.

BS. Please. "You're being a fascist" does not mean "you must be a member of or
supporter of a political party supporting fascism." One is a metaphor and/or
symbolic of the way someone may be acting and the other is an absolute.

You guys are making this way more ridiculous than it ever had to be, and the
entire thing isn't very adult at all.

>> X or Y is a facist does not say X or Y is HITLER, cmon.
>
> Correct, but I didn't claim that, so I don't see your point.

"Hitler. When you accuse someone of being a fascist, you're aligning them with


Hitler. That isn't funny."

That's *close* enough.


Richard Heathfield

unread,
Oct 3, 2006, 7:03:01 PM10/3/06
to
Frederick Gotham said:

> Is this the part where I repeatedly insist that you apologise to me for
> racial profiling?

I don't know what "racial profiling" means, and I thought you'd be proud to
be Irish, but if my words offended you, I apologise for them.

It appears no apology will be forthcoming, so I guess it's time to killfile
you.

Richard Heathfield

unread,
Oct 3, 2006, 7:12:09 PM10/3/06
to
Christopher Layne said:

> BS. Please. "You're being a fascist" does not mean "you must be a member
> of or supporter of a political party supporting fascism."

It is not an unreasonable interpretation, and one which anyone using the
word must brace themselves to expect. If Mr Gotham did not mean "fascist",
his correct course is to say so, and to withdraw the statement with an
apology. If he did mean it, of course, then there is all the more reason to
withdraw and apologise.

>>> X or Y is a facist does not say X or Y is HITLER, cmon.
>>
>> Correct, but I didn't claim that, so I don't see your point.
>
> "Hitler. When you accuse someone of being a fascist, you're aligning them
> with Hitler. That isn't funny."
>
> That's *close* enough.

No, it isn't. The difference is significant.

Keith Thompson

unread,
Oct 3, 2006, 8:07:26 PM10/3/06
to
This article contains no significant technical content. It is a
continuation of a discussion regarding personal insults. I claim that
it is marginally topical because it has to do with newsgroup
etiquette. Beyond that, I claim personal privilege to respond to
Mr. Gotham's insults. If you want to discuss C, skip this article.

Frederick Gotham <fgot...@SPAM.com> writes:
> Richard Heathfield posted:
>
>> When someone accuses *you* of being associated with the political group
>> responsible for the murder of ten million people in death camps in the
>> 1930s and 1940s, I hope you will have the courage to defend yourself
>> stalwartly against such an attack, and will not be too upset when foolish
>> people mock you for doing so.
>
> OK here's where I'm confused. When did I ever indicate that anyone had any
> association with a political group, murderers, etc.?

When you called me a fascist.

> I used the word, "fascist", to indicate a philosophy of complete power,
> forcibly suppressing opposition and criticism.

I have not forcibly suppressed anything. If you claim that I have
done so, you are lying and/or deluded. I merely expressed my opinion,
as everyone here is perfectly entitled to do.

Even if "fascist" meant only what you falsely claim it means, your use
of it to describe me would be false, insulting, libelous, and stupid.

But in fact, the word "fascist" means much more than that, as you
should know perfectly well. I've mentioned the names Mussolini,
Franco, and Hitler in this context before; I won't explain it again.

Words have meanings, even if the person using them refuses to
understand (or pretends not to understand) what he's actually saying.

> I condemned Keith's reaction to my usage of "char unsigned". Keith,
> rather than simply acknowledging that it was perfectly legal
> alternative syntax, berrated me for using it and even went so far as
> to rudely label my methods as "perverse" to a new-comer before I
> even got a chance to engage in first contact with said new-comer.

I believe I *also* explicitly acknowledged that "char unsigned" is a
legal alternative syntax. Yes, I referred to your use of "char
unsigned" as perverse. That is my *opinion*, and I continue to stand
by it. If you disagree, try making an argument rather than slinging
stupid insults.

> I also condemn the way in which he expressed his opinion with regard
> to "C==v Vs v==C"; he labelled the alternative way of doing it as
> "unbearably ugly".

groups.google.com shows two occurrences of the phrase "unbearably
ugly" in my posts to this newsgroup. Here's the first:

| Personally, I find the reversed form almost unbearably ugly (and not
| particularly useful for "!=") , but I understand the rationale for
| using it. In your program, you don't use it consistently; some tests
| have the constant on the right, some have the constant on the left.
| Consistency is your friend.

Here's the second:

| Yes, you can, but many people, including me, find that style almost
| unbearably ugly.

And you call this "fascist".

> I see a pattern of "My way is the only way of doing things,
> everything else is crap -- do it my way".

Nonsense. I expressed my opinion. I explicitly stated that it was my
own personal opinion. I acknowledged that contrary opinions are also
valid. I did not force anything on anyone. Seeing this as "fascist",
in any real or imagined sense of the word, is simply incomprehensible.

> That's why the word, "fascist", came to mind. It had nothing to do
> with politics, murder, etc..

Yes, it most certainly does. Stop being a malicious idiot.

Keith Thompson

unread,
Oct 3, 2006, 8:20:37 PM10/3/06
to
Yevgen Muntyan <muntyan.r...@tamu.edu> writes:
> Keith Thompson wrote:
[...]
>> If you prefer, try this:
>> #if CHAR_BIT != 8
>> #error "This code assumes CHAR_BIT == 8 (see the foobar module)"
>> #endif
>> It's about detecting errors as early as possible. If you have the
>> above in your code, and I try to build it on a CHAR_BIT==64 system, it
>> fails immediately; I can either give up, or try to modify the code so
>> it works on my system.
>> What alternative are you suggesting, and how is it better than
>> #error?
>
> My alternative is not to do that so one can actually try the code
> on brand-new MegaPC-2045.
>
> If you are talking about closed-source stuff, where you are the only
> person (or a member of a single group, or whatever) who compiles the
> code, then of course you want immediate build error. And then we are
> talking about different things :)
>
> My setup is like this: I have PC's with linux, FreeBSD, and windows, and
> I occasionally use other systems/architectures. It doesn't happen often
> since I don't have those systems/architectures, so user bug reports are
> very valuable. And I don't expect I will try MegaPC-2045 before users,
> they usually have better hardware than I do.

My assumption has been that the MegaPC-2045 has CHAR_BIT==64, and that
the code in question explicitly depends on the assumption that
CHAR_BIT==8.

For example, I might want to compute the number of 1 bits in a block
of memory. One good way to do that is to sum the number of 1 bits in
each byte (unsigned char), using a lookup table for each byte. I can
use a 256-element lookup table if I assume CHAR_BIT==8.

If I want to port the code to a system with CHAR_BIT==64, I *know*
that function won't work correctly (but I'll probably just silently
get wrong answers at run time, and who knows how long it will take to
track them down).

By adding the conditional #error directive, I guarantee that anyone
who tries to compile the code on a MegaPC-2045 will have his attention
forcibly draw to this issue. The text of the #error message should
provide useful information, and ideally there should also be comments
nearby, or in a separate developer document, explaining the details.
It might be as vague as, "I've only tried this code on CHAR_BIT==8
systems; it may or may not work elsewehere", or it might be as
specific as "The bit_count function definitely will not work with
CHAR_BIT!=8; I know how to make it work, but I haven't taken the time
to generalize the code". In either case, whoever is trying to compile
the code is free to comment out the "#error" and apply any necessary
fixes.

As I said, it's about catching errors as early as possible.

Keith Thompson

unread,
Oct 3, 2006, 8:32:14 PM10/3/06
to
Richard Heathfield <inv...@invalid.invalid> writes:
> Frederick Gotham said:
>
>> Is this the part where I repeatedly insist that you apologise to me for
>> racial profiling?
>
> I don't know what "racial profiling" means, and I thought you'd be proud to
> be Irish, but if my words offended you, I apologise for them.

To be fair, Richard, you did use the phrase "bull-headed Irishman".
One could reasonably infer that you meant to imply that Irishmen tend
to be bull-headed. If that wasn't what you meant, I don't know why
you included the word "Irishman".

Richard Heathfield

unread,
Oct 3, 2006, 8:37:03 PM10/3/06
to
Keith Thompson said:

> Richard Heathfield <inv...@invalid.invalid> writes:
>> Frederick Gotham said:
>>
>>> Is this the part where I repeatedly insist that you apologise to me for
>>> racial profiling?
>>
>> I don't know what "racial profiling" means, and I thought you'd be proud
>> to be Irish, but if my words offended you, I apologise for them.
>
> To be fair, Richard, you did use the phrase "bull-headed Irishman".
> One could reasonably infer that you meant to imply that Irishmen tend
> to be bull-headed.

No. If I'd thought Irishmen tend to be bull-headed, I would have considered
the adjective superfluous, and dropped it completely, you illogical
American! ;-)

> If that wasn't what you meant, I don't know why
> you included the word "Irishman".

Because the phrase rolled off the keyboard and into stdin, that's why. It
was a thoughtless thing to say, and I have apologised, so that's an end of
that part of the matter.

Chris Torek

unread,
Oct 3, 2006, 8:43:51 PM10/3/06
to
In article <efu768$q35$1...@news.tamu.edu>,
Yevgen Muntyan <muntyan.r...@tamu.edu> wrote:
>... I don't like the *code* like following:
>
>void do_init (MyStruct *obj)
>{
> obj->some_linked_list = NULL;
> obj->other_linked_list = NULL;
> obj->one_more_list = NULL;
> obj->and_a_list_again = NULL;
>}
>
>given that obj is already zero-filled.

Eric Sosman has already given most of the answer I would have.
The main thing I would like to point out above this is that -- if
the code really is very much like the fragment above -- one finds,
over time, that maintenance programmers forget the "given" part
and call do_init() with a pointer to an "obj" that is *not*
"already zero-filled":

void somefunc(void) {
MyStruct temp;
...
do_init(&temp);
do_some_work(&temp);
...
}

Interestingly, such code often works when first tested, only to
fail in strange (and sometimes difficult-to-debug) ways later.

Other than that, you can choose whether to depend on the commonly
true supposition that "all bits zero works the same as NULL". This
is not entirely universal (see the FAQ for counter-examples), and
not guaranteed to be true in future implementations, but you can
choose to depend on it anyway.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.

Tak-Shing Chan

unread,
Oct 3, 2006, 10:53:45 PM10/3/06
to
On Wed, 4 Oct 2006, Keith Thompson wrote:

[snip]

> Frederick Gotham <fgot...@SPAM.com> writes:
>> That's why the word, "fascist", came to mind. It had nothing to do
>> with politics, murder, etc..
>
> Yes, it most certainly does. Stop being a malicious idiot.

IMHO the root cause of this crisis is that both you and
Frederick have taken ``figures of speech'' literally. Frederick
takes ``perverse'' to mean something that you do not mean to mean
and you take ``fascism'' to mean something that Frederick does
not mean to mean.

It would be pointless to reconcile incompatible lexicons.
Rather, may I suggest that you s/perverse/uncommon/ and Frederick
s/fascist/elitist/? Then we can all move on.

Tak-Shing

William Ahern

unread,
Oct 3, 2006, 11:00:49 PM10/3/06
to
On Tue, 03 Oct 2006 05:01:34 -0700, Ancient_Hacker wrote:
>
> Yevgen Muntyan wrote:
>> Hey,
>>
>> Are there not highly specialized and still existing and used platforms
>> where NULL is not a sequence of zeros, so that "char *a = NULL;" and
>> "char *a; memset (&a, 0, sizeof (a));" are not equivalent?
>
>
> I can't think of any right offhand, but any architecture that has
> capability-style pointers, or segmented pointers could conceivably have
> pointers that have a non-0 bit pattern.
>
> The problem is, the dung-cart is pushing the horse these days-- the
> (commercial) guys that dream up lines on silicon are not going to waste
> space on anything that a C compiler won't emit. And non-zero NULL
> pointers are not at all popular. So it's a bit of a South-of-the-border
> imbroglio.
>
> There may be the occasional chip brewed up at Stanford that has nice
> features like structured address spaces, capability bits on each byte,
> range checking, etc, but we're likely to be stuck with the very fast and
> dumb CPU's targeted by C-like languages and policies.

What about virtual machines, and compilers which might target them? Or
compilers that emit machine code which employ smart pointers in executing
the program?

I use to be content assuming all pointer comparisons were valid, on the
assumption that I'd _never_ come across a situation where it would matter
as long as I never dereferenced them (i.e. equivocating pointer values
with all other integral values). Then I began using a compiler with a
debug mode that invalidated my assumption(s). And much like the OP's
scenario, writing code correctly in the first place imparted neither
performance costs nor any necessary labour costs (beyond educating myself).

Also, your argument about the dung-cart pushing the horse doesn't
necessarily hold up, either. AMD introduced the x86-64 architecture
sporting per-page capability bits when neither Windows nor Linux
supported such a thing.

- Bill

Yevgen Muntyan

unread,
Oct 3, 2006, 11:15:11 PM10/3/06
to

Every day something new. I didn't know standard uses wording like
"first n characters of the object", I guess I need to read it before
even mentioning it again :)

>>So, when I want to get some knowledge of C programmers out there,
>>comp.lang.c is a wrong place.
>
>
> Do you think you've been poorly served by the answers given here?

Oh, so I may keep asking off-topic questions? I thought I may not
do that, and need to find another place ;)

>>Single fact that zeroing memory gives you a crash instead of random
>>behavior very well justifies using of calloc(),
>
>
> But that is not a fact, merely an observation of the behaviour of a limited
> number of systems, and by no mean a universal fact.

I don't use a universal computer, I use what I have at home, and I do
get crash here when writing to NULL. So, a rule "use calloc() on x86 to
make your life easier (and not harder wherever else)" is not a bad
rule ("rule" is a poor word here, I guess, may we speak Russian?).
The simple bugs like not initializing structure members whre needed
may be extremely hard to debug if you use malloc(), and you don't have
to care whether writing to NULL is crash or not on any platform;
because you fix it once on your home PC thanks to zero-filled object.
I consider it as a useful feature of whole development system which
includes machine, OS, compiler, desktop environment, gdb, xchat,
and whatnot.

"Use calloc() and feel safe" is not a good rule, indeed, but it's
different.

> No, the advantage of
> zeroing memory is only this - that it allows you a fast, convenient way to
> initialise dynamic arrays of integer types.
>
>
>>unless it's expensive
>>(or is there any other objection to using calloc()?).
>
>
> Only that it's pointless, except in the case of arrays of integer types.

Do you also not use valgrind because it's linux-i386 only?

Regards,
Yevgen

Ian Collins

unread,
Oct 3, 2006, 11:17:54 PM10/3/06
to
Frederick Gotham wrote:
>
> I condemned Keith's reaction to my usage of "char unsigned". Keith, rather
> than simply acknowledging that it was perfectly legal alternative syntax,
> berrated me for using it and even went so far as to rudely label my methods
> as "perverse" to a new-comer before I even got a chance to engage in first
> contact with said new-comer.

perverse - marked by a disposition to oppose and contradict.

Nicely describes stubbornly promoting something 99.lots of others
consider arse about face.

--
Ian Collins.

Yevgen Muntyan

unread,
Oct 3, 2006, 11:28:27 PM10/3/06
to
Chris Torek wrote:
>
> Eric Sosman has already given most of the answer I would have.
> The main thing I would like to point out above this is that -- if
> the code really is very much like the fragment above -- one finds,
> over time, that maintenance programmers forget the "given" part
> and call do_init() with a pointer to an "obj" that is *not*
> "already zero-filled":
>
> void somefunc(void) {
> MyStruct temp;
> ...
> do_init(&temp);
> do_some_work(&temp);
> ...
> }
>
> Interestingly, such code often works when first tested, only to
> fail in strange (and sometimes difficult-to-debug) ways later.

Well, here's more details: those init() function are called for
objects from GObject type system, a type system provided by
glib (http://gtk.org). The code of those init() functions is usually
highly GObject-specific, and glib guarantees zero-filled objects.
Moreover, noone in his right mind will call those init() functions
manually, because they serve purpose analogous to C++ constructors;
one important thing about them is that base class init() must be called
first.
Of course you could take GObject code, and remove GObject stuff
from it, but well, it's always dangerous to copy/paste (or refactor,
to use a fancy word) code without taking into account exact conditions
this code assumes.

And another case where you explicitely do stuff like
x = calloc(1, sizeof(T));
x->something = blah;
does not suffer from the problem above - calloc() call here is part
of object initialization, and you can't just replace it with malloc()
and pretend it should still work right.

> Other than that, you can choose whether to depend on the commonly
> true supposition that "all bits zero works the same as NULL". This
> is not entirely universal (see the FAQ for counter-examples), and
> not guaranteed to be true in future implementations, but you can
> choose to depend on it anyway.

Or, to be more precise, I assume that gtk will not work on a platform
where NULL is not all zero bits any soon. It's not just a new fancy
platform need to appear, it should also get desktop users.

Best regards,
Yevgen

Christopher Layne

unread,
Oct 4, 2006, 12:48:59 AM10/4/06
to
Yevgen Muntyan wrote:

> "Use calloc() and feel safe" is not a good rule, indeed, but it's
> different.

Yes, but it's also a "I don't trust my own programming" rule. I use calloc
where it's convenient and will kill multiple birds with one stone. Tail
chasing as a result of not properly initing (or otherwise) after malloc() is
my own fault, no one elses.

Keith Thompson

unread,
Oct 4, 2006, 1:21:15 AM10/4/06
to

I don't *entirely* agree, but I've been giving this some thought and
I'd like to say a few things.

I don't believe that Frederick misunderstood my use of the word
"perverse". When he initially took offense at it, I thought he might
have mistaken it for the word "perverted", and I quoted a dictionary
definition. He made it clear that he understood what I meant, and he
found it offensive.

What I wrote at the time, and what I meant and still mean, is that I
find Frederick's use of things like "char unsigned" rather than the
more common "unsigned char" to be needlessly contrary to common usage.
It is, of course, perfectly legal as far as the language definition is
concerned (though I'll note that the standard does not use Frederick's
form in any examples), but it is, as far as I can tell, different
merely for the sake of being different. I honestly don't know why
Frederick chooses to re-order keywords like this. I see absolutely no
advantage of his style over the more common style, and much potential
for confusion. That's why I tried to warn a newbie away from it.

The word "perverse" has several meanings; some of them are more severe
than what I intended. I don't find "char unsigned" deeply offensive
or evil. I do find it needlessly contrary, and I dislike it. (I
think he's attempted some sort of explanation, but I can't be bothered
to go back and look it up.)

I criticized his coding style. I did not intend it as a personal
insult. This is a C language style point on which reasonable people
can disagree. And if Frederick had chosen to discuss this on its
technical merits, it might have been an interesting discussion.

I accept that Frederick did not actually intend to compare me to
Hitler, Mussolini, and/or Franco. I am still bewildered that he can't
understand that it came across that way, but I suppose I'll let that
go. I'll drop the Hitler portion of this dispute.

However, even accepting Frederick's claimed definition of "fascist",
his accusation is absurd and insulting. He wrote, elsewhere in this
thread:

| I used the word, "fascist", to indicate a philosophy of complete power,
| forcibly suppressing opposition and criticism.

I have no such philosophy; quite the opposite, in fact. The only
power I exercise in this newsgroup is choosing for myself what to
write and what not to write. I have exerted no force whatsoever,
unless you consider persuasion to be a form of force (I do not). I
have suppressed nothing. Frederick is exactly as free as he as always
been to oppose or criticize anything he likes. And so am I.

I have expressed my opinions here. For the most part, I have
expressed opinions about people's code, their writings, and their
behavior. I have expressed (negative) opinions about people
themselves only under extreme provocation. And for this, I am accused
of "forcibly suppressing opposition and criticism".

Frederick, I can understand that repeated demands for an apology are
unlikely to be effective. I have a considerable stubborn streak
myself (and I am not using the word "stubborn" as an insult). So let
me just ask you this. Do you understand why I was so offended by your
remarks? Can you justify your statement that I have been "forcibly
suppressing opposition and criticism"? And if you can't, will you
withdraw it?

Richard Heathfield

unread,
Oct 4, 2006, 3:12:29 AM10/4/06
to
Yevgen Muntyan said:

> Richard Heathfield wrote:
>> Yevgen Muntyan said:
>>

<snip>


>
>>>So, when I want to get some knowledge of C programmers out there,
>>>comp.lang.c is a wrong place.
>>
>> Do you think you've been poorly served by the answers given here?
>
> Oh, so I may keep asking off-topic questions?

No, but a question about representation of null pointers is surely topical.

> I thought I may not
> do that, and need to find another place ;)
>
>>>Single fact that zeroing memory gives you a crash instead of random
>>>behavior very well justifies using of calloc(),
>>
>> But that is not a fact, merely an observation of the behaviour of a
>> limited number of systems, and by no mean a universal fact.
>
> I don't use a universal computer, I use what I have at home, and I do
> get crash here when writing to NULL.

Well, you know you sometimes do. You don't know you always do, unless your
system vendor documents that you do.

<snip>

>>>(or is there any other objection to using calloc()?).
>>
>>
>> Only that it's pointless, except in the case of arrays of integer types.
>
> Do you also not use valgrind because it's linux-i386 only?

No, actually; the reason I don't use valgrind is that I don't need to. :-)

CBFalconer

unread,
Oct 4, 2006, 5:42:00 AM10/4/06
to
Keith Thompson wrote:

> Christopher Layne <cla...@com.anodized> writes:
>> Keith Thompson wrote:
>>
... snip ...
>>>
>>> For example:
>>>
>>> struct foo {
>>> int i;
>>> double d;
>>> void *p;
>>> };
>>> const struct foo foo_zero = { 0 };
>>
>> Also, couldn't he just init a global object with the standard inits
>> he wants, and memcpy it into place after malloc()? I mean, if
>> per-member initialization is such a big deal and he's worried about
>> machines with NULL == (void *)1564. Personally I think a global
>> default is kind of "ghetto." but hey, if it really bothers him that
>> much to init each member.
>
> ("ghetto?")
>
> You can assign structures; there's no need to use memcpy().
>
> If the global object is const, as I defined it above, there's no real
> problem with making it global.

However if it is const you will not be able (barring tortuous icky
code) to make the initial value of p legitimate. I suggest:

struct foo *getzerofoo(void) {
struct foo foozp;

if (foozp = malloc(sizeof *foozp)) {
foozp->i = 0;
foozp->d = 0.0;
foozp->p = NULL;
}
return foozp;
}

and you can either use this to get each fooz, or once to get a
zeroed value:

struct foo fz;
const struct foo * const zerofoop = getzerofoo();
....
fz = *zerofoop;

--
Some informative links:
<news:news.announce.newusers
<http://www.geocities.com/nnqweb/>
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/>


CBFalconer

unread,
Oct 4, 2006, 6:12:57 AM10/4/06
to
Frederick Gotham wrote:
>
... snip ...

>
> OK here's where I'm confused. When did I ever indicate that anyone
> had any association with a political group, murderers, etc.?
>
> I used the word, "fascist", to indicate a philosophy of complete
> power, forcibly suppressing opposition and criticism.

There you are. Fascist has many more connotations, few of which
are good. The fact that you are (possibly) too ignorant to realize
this is no excuse.

CBFalconer

unread,
Oct 4, 2006, 6:39:20 AM10/4/06
to
Richard Heathfield wrote:
> Keith Thompson said:
>
> <snip>

>
>> As far as I know, the C90 standard doesn't explicitly guarantee
>> that all-bits-zero is a representation of 0 for integer types.
>
> Yeah, we used to raise this all the time. Some years ago, though,
> ISO got sick of being hassled about it and said something along
> the lines of "yes, yes, YES already! We guarantee it! Now be gone,
> and stop giving headache all of time. Where did I leave that beer?".
>
> Ask in comp.std.c for details. :-)

As I believe they have recently for double, float, etc. I saw
somewhere that they had researched it and found no machines of any
vintage where that was not true, and thus the requirement could be
added.

CBFalconer

unread,
Oct 4, 2006, 6:23:47 AM10/4/06
to
Keith Thompson wrote:
> Richard Heathfield <inv...@invalid.invalid> writes:
>> Frederick Gotham said:
>>
>>> Is this the part where I repeatedly insist that you apologise
>>> to me for racial profiling?
>>
>> I don't know what "racial profiling" means, and I thought you'd
>> be proud to be Irish, but if my words offended you, I apologise
>> for them.
>
> To be fair, Richard, you did use the phrase "bull-headed Irishman".
> One could reasonably infer that you meant to imply that Irishmen
> tend to be bull-headed. If that wasn't what you meant, I don't
> know why you included the word "Irishman".

Gotham is known to be an Irishman. That is not an insult (in most
societies). Many people are bull-headed (including myself at
times) without being Irish. Simultaneously many Irish are not
bull-headed.

Richard Heathfield

unread,
Oct 4, 2006, 6:55:04 AM10/4/06
to
CBFalconer said:

> Richard Heathfield wrote:
>> Keith Thompson said:
>>
>> <snip>
>>
>>> As far as I know, the C90 standard doesn't explicitly guarantee
>>> that all-bits-zero is a representation of 0 for integer types.
>>
>> Yeah, we used to raise this all the time. Some years ago, though,
>> ISO got sick of being hassled about it and said something along
>> the lines of "yes, yes, YES already! We guarantee it! Now be gone,
>> and stop giving headache all of time. Where did I leave that beer?".
>>
>> Ask in comp.std.c for details. :-)
>
> As I believe they have recently for double, float, etc. I saw
> somewhere that they had researched it and found no machines of any
> vintage where that was not true, and thus the requirement could be
> added.

If that is indeed the case, then it's very significant indeed. What's your
source?

Christopher Layne

unread,
Oct 4, 2006, 8:13:11 AM10/4/06
to
Richard Heathfield wrote:

>> Do you also not use valgrind because it's linux-i386 only?
>
> No, actually; the reason I don't use valgrind is that I don't need to. :-)
>

You can predict cache efficiency in your head? VG isn't just find-a-leak.

Richard Heathfield

unread,
Oct 4, 2006, 8:22:27 AM10/4/06
to
Christopher Layne said:

> Richard Heathfield wrote:
>
>>> Do you also not use valgrind because it's linux-i386 only?
>>
>> No, actually; the reason I don't use valgrind is that I don't need to.
>> :-)
>>
>
> You can predict cache efficiency in your head?

Why would I need to? If the program's fast enough, it's fast enough, and if
it isn't, my first port of call will be gprof, not valgrind, because I'll
be looking for serious bottlenecks, not cache twiddlings.

Antti-Juhani Kaijanaho

unread,
Oct 4, 2006, 8:35:35 AM10/4/06
to
Yevgen Muntyan <muntyan.r...@tamu.edu> kirjoitti 04.10.2006:
> Do you also not use valgrind because it's linux-i386 only?

It's not. (I run it happily on my non-i386 Linux laptop:)

Yevgen Muntyan

unread,
Oct 4, 2006, 9:03:50 AM10/4/06
to

Oh, good to know. Perhaps I just misinterpreted something
as usual.
But it confirms my point: you don't need stuff that works
everywhere to use it successfully, you don't even need to
know if it works anywhere but your development platform;
yo only need to know it doesn't hurt anywhere ;)

Regards,
Yevgen

Christopher Benson-Manica

unread,
Oct 4, 2006, 9:24:39 AM10/4/06
to
Richard Heathfield <inv...@invalid.invalid> wrote:

(Thought I already posted this, but I don't see it. Apologies if this
is a duplicate.)

> You can start by thinking about apologising to Keith for behaving abusively
> and libellously towards him in this newsgroup.

Would it be possible for you and Keith to prepend some identifying
text to the subject of these apology request posts? While I support
the position that you (plural) have taken, such posts and the ensuing
back and forth about semantics have ceased to be interesting.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.

Richard Heathfield

unread,
Oct 4, 2006, 9:30:04 AM10/4/06
to
Christopher Benson-Manica said:

> Would it be possible for you and Keith to prepend some identifying
> text to the subject of these apology request posts?

Heh - touche'. No, seriously, I'm done. I thought Frederick was clueful
enough to take a hint if it were dropped enough times, but alas, it appears
not. I've killfiled him.

> While I support
> the position that you (plural) have taken,

Thank you.

> such posts and the ensuing
> back and forth about semantics have ceased to be interesting.

They never were interesting. And neither is this reply, alas.

Antti-Juhani Kaijanaho

unread,
Oct 4, 2006, 9:17:05 AM10/4/06
to
Yevgen Muntyan <muntyan.r...@tamu.edu> kirjoitti 04.10.2006:
> Antti-Juhani Kaijanaho wrote:
>> Yevgen Muntyan <muntyan.r...@tamu.edu> kirjoitti 04.10.2006:
>>>Do you also not use valgrind because it's linux-i386 only?
>> It's not. (I run it happily on my non-i386 Linux laptop:)
>
> Oh, good to know. Perhaps I just misinterpreted something
> as usual.

It used to be i386 only but nowadays supports amd64 (x86_64) and powerpc
as well (under Linux).

(This is all off topic, of course. ObC: I used valgrind recently to
debug a C89 program that contains a copying garbage collector. To the
best of my knowledge, the program does not use any nonstandard features.)

Clark S. Cox III

unread,
Oct 4, 2006, 9:33:07 AM10/4/06
to
CBFalconer wrote:
> Keith Thompson wrote:
>> Christopher Layne <cla...@com.anodized> writes:
>>> Keith Thompson wrote:
>>>
> .... snip ...

>>>> For example:
>>>>
>>>> struct foo {
>>>> int i;
>>>> double d;
>>>> void *p;
>>>> };
>>>> const struct foo foo_zero = { 0 };
>>> Also, couldn't he just init a global object with the standard inits
>>> he wants, and memcpy it into place after malloc()? I mean, if
>>> per-member initialization is such a big deal and he's worried about
>>> machines with NULL == (void *)1564. Personally I think a global
>>> default is kind of "ghetto." but hey, if it really bothers him that
>>> much to init each member.
>> ("ghetto?")
>>
>> You can assign structures; there's no need to use memcpy().
>>
>> If the global object is const, as I defined it above, there's no real
>> problem with making it global.
>
> However if it is const you will not be able (barring tortuous icky
> code) to make the initial value of p legitimate.

Why do you say that? Statics/globals are zero initialized.

--
Clark S. Cox III
clar...@gmail.com

Christopher Benson-Manica

unread,
Oct 4, 2006, 8:32:31 AM10/4/06
to
Richard Heathfield <inv...@invalid.invalid> wrote:

> You can start by thinking about apologising to Keith for behaving abusively
> and libellously towards him in this newsgroup.

Would it be possible for you and Keith to prepend these
apology-request posts with some identifying text, say [APP], so the
rest of us who are not involved in the situation can remain so?

Richard Heathfield

unread,
Oct 4, 2006, 10:21:48 AM10/4/06
to
Christopher Benson-Manica said:

> Richard Heathfield <inv...@invalid.invalid> wrote:
>
>> You can start by thinking about apologising to Keith for behaving
>> abusively and libellously towards him in this newsgroup.
>
> Would it be possible for you and Keith to prepend these
> apology-request posts with some identifying text, say [APP], so the
> rest of us who are not involved in the situation can remain so?

"For evil to triumph, it is only necessary that good men do nothing."
- attrib Edmund Burke.

Frederick Gotham

unread,
Oct 4, 2006, 1:45:31 PM10/4/06
to
Keith Thompson posted:

> My assumption has been that the MegaPC-2045 has CHAR_BIT==64, and that
> the code in question explicitly depends on the assumption that
> CHAR_BIT==8.
>
> For example, I might want to compute the number of 1 bits in a block
> of memory. One good way to do that is to sum the number of 1 bits in
> each byte (unsigned char), using a lookup table for each byte. I can
> use a 256-element lookup table if I assume CHAR_BIT==8.
>
> If I want to port the code to a system with CHAR_BIT==64, I *know*
> that function won't work correctly (but I'll probably just silently
> get wrong answers at run time, and who knows how long it will take to
> track them down).


Maybe something like:

#include <limits.h>
#include <assert.h>

#ifndef __STDC_VERSION__
#define inline
#define restrict
#elif __STDC_VERSION__ < 199901L
#define inline
#define restrict
#endif

inline
unsigned QuantBitsSetInOctet(unsigned const val)
{
static char unsigned const table[256] =

{0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,
2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,
2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,
4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,
2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,
4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,
4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,
6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,
2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,
4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,
4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,
6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,
4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,
6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,
6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};

return assert(val <= 255),table[val];
}

inline
unsigned QuantBitsSetInByte(char unsigned val)
{
#if CHAR_BIT==8
return QuantBitsSetInOctet(val);
#else

unsigned quant = QuantBitsSetInOctet(val&255U);

#if CHAR_BIT%8
unsigned i = 0;
#else
unsigned i = 1;
#endif

do quant += QuantBitsSetInOctet(val>>=8);
while(CHAR_BIT/8 != ++i);

return quant;

#endif
}

--

Frederick Gotham

Kindly refrain from replying if your reply is vacuous. This includes:

(1) Indicating that you refuse to reply.
(2) Indicating that you shall not reply until a particular event occurs.
(3) Demanding that I not respond to you.


Christopher Benson-Manica

unread,
Oct 4, 2006, 1:50:55 PM10/4/06
to
Yevgen Muntyan <muntyan.r...@tamu.edu> wrote:

> It is useless on given machines after x is allocated with calloc().
> Maybe "useless" is not the right word here, I mean something like
> "unnecessary extra code which in effect does nothing but eating
> valuable screen space" :)

I think the solution is to get yourself a nice big monitor and
possibly an editor that will fold that code for you. If screen real
estate is important enough to you that you will make coding decisions
based on preserving it, those two courses of action seem obvious.

> void do_init (MyStruct *obj)
> {
> obj->some_linked_list = NULL;
> obj->other_linked_list = NULL;
> obj->one_more_list = NULL;
> obj->and_a_list_again = NULL;
> }

At the very least, you could do yourself and those who maintain your
code a potentially enormous favor by inserting a comment in this
do_int() function detailing the assumptions you've described
elsethread.

Frederick Gotham

unread,
Oct 4, 2006, 1:52:55 PM10/4/06
to
Richard Heathfield posted:

> I don't think I'm being unreasonable in claiming that, by describing
> Keith as a Fascist, Mr Gotham was stating that Keith is an exponent or
> supporter of Fascism or, at least, has extreme right-wing nationalistic
> views or methods.


Reasonable... who knows? Correct... no.

> Keith has every right to expect an apology for this unjust accusation.


Now you falsely accuse me of falsely accusing someone else of having an
affiliation with right-wing nationalistic views or methods.


>> X or Y is a facist does not say X or Y is HITLER, cmon.
>
> Correct, but I didn't claim that, so I don't see your point.


You explicitly said my statement aligned him with Hitler.

--

Kindly refrain from replying if your reply is vacuous. This includes:

(1) Indicating that you refuse to reply.
(2) Indicating that you shall not reply until a particular event occurs.
(3) Demanding that I not respond to you.

Frederick Gotham

Keith Thompson

unread,
Oct 4, 2006, 2:08:32 PM10/4/06
to

Or you can just do what I did above:

struct foo {
int i;
double d;
void *p;
};
const struct foo foo_zero = { 0 };

which sets foo_zero.i to 0, foo_zero.d to 0.0, and foo_zero.p to NULL,
regardless of the representations of 0.0 and NULL.

Keith Thompson

unread,
Oct 4, 2006, 2:12:56 PM10/4/06
to
Christopher Benson-Manica <at...@otaku.freeshell.org> writes:
> Richard Heathfield <inv...@invalid.invalid> wrote:
>
> (Thought I already posted this, but I don't see it. Apologies if this
> is a duplicate.)
>
>> You can start by thinking about apologising to Keith for behaving abusively
>> and libellously towards him in this newsgroup.
>
> Would it be possible for you and Keith to prepend some identifying
> text to the subject of these apology request posts? While I support
> the position that you (plural) have taken, such posts and the ensuing
> back and forth about semantics have ceased to be interesting.

Agreed. I've started using "[OT]", and will make sure I continue to
do so. (I might consider something more specific, but I don't expect
there to be a whole lot more postings.)

It is loading more messages.
0 new messages