Equivalent malloc with calloc

  • Thread starter lovecreatesbea...
  • Start date
K

Kenneth Brody

Keith said:
The NULL macro "expands to an implementation-defined null pointer
constant" (C99 7.17p3).

The term "null pointer constant" is defined in C99 6.3.2.3p3:

An integer constant expression with the value 0, or such an
expression cast to type void *, is called a null pointer constant.

But, if the 6.3.2.3p3 definition of "null pointer constant" is "an
integer constant expression with the value 0 .. cast to type void *",
then why does 7.17p3 say that NULL "expand to an implementation-
defined null pointer constant"? If it must be zero, why say that is
is "implementation-defined"? Why not say it is "((void *)0)"?

Doesn't 6.3.2.3p3 say that zero, cast to void * is _a_ null pointer
constant? It doesn't say that no other void * can be a null pointer
constand, does it?
"((void*)&MyNullAddress)" doesn't qualify. Furthermore, a "null
pointer" (as distinct from a "null pointer constant") "is guaranteed
to compare unequal to a pointer to any object or function";
"((void*)&MyNullAddress)" fails on that count as well.

What if __MyNullAddress isn't a real object, but a magic name? Or
perhaps &__MyNullAddress doesn't point to any object. Perhaps it is
magically placed outside the address space of the current process.
Although C99 6.6p10 says:

An implementation may accept other forms of constant expressions.

But of course the conversion of the integer constant 0 to a pointer
type yields an implementation-specific pointer representation, and I
believe that representation can legitimately vary from one execution
of a program to another, as long as it's always treated as a null
pointer within each execution.

Note that the "%p" format used by fprintf() and fscanf() doesn't
restrict the implementation's flexibility here; the converted value is
required to work only during the same program exexution, and there's
no stated exception for null pointers.

Of course, I'm not saying that it necessarily makes sense to do
such strange things, but perhaps an all-bits-zero pointer is a valid
address as far as the hardware is concerned, and you wanted to make
sure that dereferencing NULL would trigger a hardware trap. Perhaps
the way to do that would be to have &__MyNullAddress evaluate to the
start of the next 4K boundary after the end of the initial stack
pointer?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Keith Thompson

Kenneth Brody said:
But, if the 6.3.2.3p3 definition of "null pointer constant" is "an
integer constant expression with the value 0 .. cast to type void *",
then why does 7.17p3 say that NULL "expand to an implementation-
defined null pointer constant"? If it must be zero, why say that is
is "implementation-defined"? Why not say it is "((void *)0)"?

The standard intentionally allows implementations some flexibility in
how they define NULL. There are a large (potentially infinite, I
suppose) number of valid null pointer constants. An implementation
could define NULL as any of:

0
0L
('-'-'-')
((void*)0)
((void*)'\0')
((void*)('/'/'/'-'/'/'/'))

(There's a pedantic argument that it can't be a parenthesized
expression, but that's a glitch in the wording of the standard, not
the actual intent.)

As for why this flexibility is permitted, I'm not sure. I suppose
there was some backward compatibility issue, but yes, the standard
*could* have required
#define NULL ((void*)0)
Doesn't 6.3.2.3p3 say that zero, cast to void * is _a_ null pointer
constant? It doesn't say that no other void * can be a null pointer
constand, does it?

Not just zero, but an integer constant expression with the value 0.
Since that's the *definition* of the term "null pointer constant"
(it's in italics) I believe it's intended to be exhaustive.
What if __MyNullAddress isn't a real object, but a magic name? Or
perhaps &__MyNullAddress doesn't point to any object. Perhaps it is
magically placed outside the address space of the current process.

Sure, you can do all sorts of magic, as long as a program can't tell
the difference. But if __MyNullAddress isn't an object, it doesn't
make much sense to take its address. For "((void*)&MyNullAddress)" to
be a null pointer constant, you'd have to have an extension that
treats "&__MyNullAddress" as an integer constant expression with the
value 0.

As long as you're doing magic, you might as well create a magic null
pointer constant that doesn't require applying the unary "&" operator
to something that isn't really an object.

In fact, if I wanted to enable the compiler to catch incorrect uses of
NULL, I'd probably declare:

enum { __NULL__ = 0 };
#define NULL __NULL__

Even without additional compiler support, this is a legitimate
definition (since __NULL__ is in the implementation's namespace). But
a compiler could recognize any use of __NULL__ in a non-pointer
context, and issue a warning.

[...]
Of course, I'm not saying that it necessarily makes sense to do
such strange things, but perhaps an all-bits-zero pointer is a valid
address as far as the hardware is concerned, and you wanted to make
sure that dereferencing NULL would trigger a hardware trap. Perhaps
the way to do that would be to have &__MyNullAddress evaluate to the
start of the next 4K boundary after the end of the initial stack
pointer?

Sure, you could do something like that, but it's not necessary to
create a magic pseudo-object. Any null pointer constant, evaluated in
a pointer context, yields a null pointer value. This:

void *ptr = 0;

*must* set ptr to a null pointer, regardless of how a null pointer is
represented. Adding magic to be used in the definition of the NULL
macro doesn't help for null pointer constants that don't use the NULL
macro.
 
A

army1987

I did, before I posted. Checked dozens of them, starting from
ASCII-1963 through many ASCIIs, GOSTs, JISCII, Thai and Vietnamese
standards, several different EBCIDCs and Soviet EBCDIC rip-offs,
several of the base ECMA standards which later became the core ISO
character set standards, ISO 646, ISO 8859, Unicode. I didn't use the
official Standard documents in many cses, but did in several of them.
Yes, I was bored.

Sometimes value 0 is undefined, other times it represents some other
character. In most cases it has what is variously described as an
acronym, abbreviation, or name of "NUL". In the important modern
standards, "NUL" is the short form, and the English form of the
character name is "NULL". I never saw it called "nul".

So the correct thing to call it in C is the "null character". With the
added restriction that we're thinking in terms of the modern Standard
character sets, it is reasonable to call it both "NUL" and "NULL". The
latter would be a confusing and unfortunate choice in a C context for
obvious reasons.

#include <stdlib.h>
#include <stdio.h>
#define NUL '\0'
int main(void)
{
if (NUL == (char)NULL && NULL == (void *)NUL)
puts("Why?");
if (NULL == NUL)
puts("They're quite the same...");
if (sizeof NUL == sizeof(int)) {
puts("Remember that character constants have type int (FAQ
8.9).");
puts("So there isn't any difference between \'\\0\' and 0.");
}
puts("On some systems, NULL is defined as 0, rather than (void
*)0.");
if (sizeof(void *) != sizeof(int)) {
if (sizeof NULL == sizeof(int))
puts("Yours is one of them.");
else
puts("Yours isn't one of them.");
} else
puts("I can't tell wheter yours is one of them.");
puts("On these systems, there is no difference between NULL and 0,
either.");
/*if (sizeof NULL == sizeof NUL && (NULL ^ NUL) == 0x0000)
* puts("On your system, there's no f***ing difference between NULL
and"
* "NUL."); */
/* On systems where NULL is defined as (void *)0 the if statement in
the
* comment above won't compile. */
puts("Even on those systems, if you want your code to be human
readable,");
puts("you should use \'\\0\' for characters and NULL for
pointers.");
puts("But that's just a matter of style: you could simply use 0 for
both.");
return 0;
}
 
G

Guest

puts("On some systems, NULL is defined as 0, rather than (void
*)0.");
if (sizeof(void *) != sizeof(int)) {
if (sizeof NULL == sizeof(int))
puts("Yours is one of them.");

sizeof NULL != sizeof(void *) only means that NULL is not defined as
((void *) 0), not that it is defined as 0. #define NULL 0L can make
sense for some implementations.
 
F

Flash Gordon

Harald van Dijk wrote, On 13/04/07 17:38:
sizeof NULL != sizeof(void *) only means that NULL is not defined as
((void *) 0), not that it is defined as 0. #define NULL 0L can make
sense for some implementations.

Whilst it is legal, I can't see what advantage it gives. After all, the
compiler would still have to be able to cope with a plain 0.
 
A

Army1987

Harald van D?k said:
sizeof NULL != sizeof(void *) only means that NULL is not defined as
((void *) 0), not that it is defined as 0. #define NULL 0L can make
sense for some implementations.

My program would then print "Yours isn't one of them." [i.e. of those who
#define NULL 0], supposing sizeof(long) > sizeof(int) (if it isn't it makes
no sense to #define NULL 0L) in the case sizeof(void *) != sizeof(int), and
"I can't tell wheter yours is one of them.", which can't be wrong,
otherwise.

The only error is I should've written "...rather than for example (void
*)0." instead of "...rather than (void *)0."
 
G

Guest

Army1987 said:
Harald van D?k said:
sizeof NULL != sizeof(void *) only means that NULL is not defined as
((void *) 0), not that it is defined as 0. #define NULL 0L can make
sense for some implementations.

My program would then print "Yours isn't one of them." [i.e. of those who
#define NULL 0], supposing sizeof(long) > sizeof(int) (if it isn't it makes
no sense to #define NULL 0L)

I actually answered that already in another message: headers can be
shared between systems where sizeof(long) > sizeof(int) and systems
where sizeof(long) == sizeof(int).
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top