Discussion:
"PORTING C" > NULL problem!
(too old to reply)
Robby
2010-02-08 23:30:01 UTC
Permalink
Hello,

As you all know, I used to use a non C compliant compiler. Now in the new C
compiler, I declared a NULL in a header file like this:

#define NULL 0

so I could pass NULL as a function parameter... stuff like this:

void f1(var1, NULL); ..... and so forth.

I recently upgraded the compiler's version and now this still works but the
compiler gives the follwoing warnings

KERNEL.h:53:1: warning: "NULL" redefined
In file included from C:/Program Files (x86)/Microchip/MPLAB C32
Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/GenericTypeDefs.h:58,

from C:/Program Files (x86)/Microchip/MPLAB C32
Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/peripheral/i2c.h:50,

from C:/Program Files (x86)/Microchip/MPLAB C32
Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/plib.h:46,

C:/Program Files (x86)/Microchip/MPLAB C32
Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/stddef.h:67:1:
warning: this is the location of the previous definition

which I think means they have added a new definition of NULL in one of their
files of their new compiler's version. So on the last warning above I double
clicked on it an it took me to the following line of the stddef.h file:

... other code
#ifndef __cplusplus
#define NULL ((void *)0) // <<<<<<<<<<<<<<
...other code

Now I know this question is probably better posted in the compiler's
specific forum, but I would like to ask something about the language. What
does this say exactly:

#define NULL ((void *)0)

NULL is a void pointer?? which still means 0 right?
So if I use NULL anywhere, I am substituting it by 0 right?

Why would someone do this as opposed to just do this:

#define NULL 0

All feedback greatly appreciated!
--
Best regards
Roberto
Igor Tandetnik
2010-02-09 00:49:05 UTC
Permalink
Post by Robby
As you all know, I used to use a non C compliant compiler. Now in the new C
#define NULL 0
Do you have to? NULL should be defined in standard headers that come with any decent C compiler.
Post by Robby
I recently upgraded the compiler's version and now this still works but the
compiler gives the follwoing warnings
KERNEL.h:53:1: warning: "NULL" redefined
In file included from C:/Program Files (x86)/Microchip/MPLAB C32
Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/GenericTypeDefs.h:58,
Precisely my point.
Post by Robby
Now I know this question is probably better posted in the compiler's
specific forum, but I would like to ask something about the language. What
#define NULL ((void *)0)
0 cast to void*
Post by Robby
NULL is a void pointer??
In C, typically, yes.
Post by Robby
which still means 0 right?
I'm not sure I understand this question.

This is what C standard has to say:

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.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

6.3.2.3p4 Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.

Footnote 55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.
Post by Robby
#define NULL 0
This is equally valid, and in fact this is how it's usually done in C++ ( ((void*)0) doesn't work in C++ because void* pointer is not implicitly convertible to other pointer types, the way it is in C). One possible reason to use ((void*)0) is that you would expect sizeof(NULL) to be equal to sizeof(void*) and not sizeof(int) (pointers don't have to be the same size as int).
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Robby
2010-02-09 02:20:01 UTC
Permalink
Post by Igor Tandetnik
Post by Robby
As you all know, I used to use a non C compliant compiler. Now in the new C
#define NULL 0
Do you have to? NULL should be defined in standard headers that come with any decent C compiler.
hum! Well, what if I do this for my own null:

#define null 0

I do this because sometimes I have a function's parameter that takes an
integer. Now, in this function, if this integer is 1 it will do one thing, if
its 2, it will do another and if its 3, it will do even another, but if its
0, it will reset some stuff and do none of the the other things. So sometimes
its possible that I would need that integer to be passed in as 0, so I call
the function like this:

void f1(NULL);

well now it will be:

void f1(null);

or I could simply do:

void f1(0);

But then, at first glance when I look at the latter function, I think that
the function does some mathematical operation..... instead if I look at the
former, I know that that parameter is used to carry out a certain mode of
operation in the function. So what is best in these types of scenarios?
Post by Igor Tandetnik
Post by Robby
I recently upgraded the compiler's version and now this still works but the
compiler gives the follwoing warnings
KERNEL.h:53:1: warning: "NULL" redefined
In file included from C:/Program Files (x86)/Microchip/MPLAB C32
Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/GenericTypeDefs.h:58,
Precisely my point.
Post by Robby
Now I know this question is probably better posted in the compiler's
specific forum, but I would like to ask something about the language. What
#define NULL ((void *)0)
0 cast to void*
Post by Robby
NULL is a void pointer??
In C, typically, yes.
Post by Robby
which still means 0 right?
I'm not sure I understand this question.
Isn't a void pointer's value 0 ? Or should I ask, what is the difference
between a void pointer's value and the value of 0.
Post by Igor Tandetnik
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.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
6.3.2.3p4 Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
Footnote 55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.
Post by Robby
#define NULL 0
This is equally valid, and in fact this is how it's usually done in C++ ( ((void*)0)
doesn't work in C++ because void* pointer is not implicitly convertible to other pointer types, the way it is in C). One possible reason to use ((void*)0) is that you would expect sizeof(NULL) to be equal to sizeof(void*) and not sizeof(int) (pointers don't have to be the same size as int).
Thanks Igor.
Pavel A.
2010-02-09 02:43:14 UTC
Permalink
Post by Robby
#define null 0
I do this because sometimes I have a function's parameter that takes an
integer. Now, in this function, if this integer is 1 it will do one thing, if
its 2, it will do another and if its 3, it will do even another, but if its
0, it will reset some stuff and do none of the the other things. So sometimes
its possible that I would need that integer to be passed in as 0, so I call
void f1(NULL);
void f1(null);
void f1(0);
..................................
By convention (or even by standard?), NULL is null pointer, not numeric 0.
For what you want, there are enums:

enum xxxx {
reset_some stuff = 0,
do_one_thing= 1,
........ etc.........
}

f( reset_some stuff );

--pa
Robby
2010-02-09 16:42:01 UTC
Permalink
Post by Pavel A.
Post by Robby
#define null 0
I do this because sometimes I have a function's parameter that takes an
integer. Now, in this function, if this integer is 1 it will do one thing, if
its 2, it will do another and if its 3, it will do even another, but if its
0, it will reset some stuff and do none of the the other things. So sometimes
its possible that I would need that integer to be passed in as 0, so I call
void f1(NULL);
void f1(null);
void f1(0);
..................................
By convention (or even by standard?), NULL is null pointer, not numeric 0.
enum xxxx {
reset_some stuff = 0,
do_one_thing= 1,
........ etc.........
}
f( reset_some stuff );
Yes I do this too in my code, but now I feel confirmed that enum is the
right chioce that should be used for this. I use enum alot and I also use
null as a 0 parameter, I think I will stop doing that.

Thanks Pavel.

Rob
Igor Tandetnik
2010-02-09 05:11:45 UTC
Permalink
Post by Robby
Post by Igor Tandetnik
Post by Robby
As you all know, I used to use a non C compliant compiler. Now in the new C
#define NULL 0
Do you have to? NULL should be defined in standard headers that come with any decent C compiler.
#define null 0
I do this because sometimes I have a function's parameter that takes an
integer.
I wouldn't if I were you. You would not use the word "apple" to describe an orange: it makes equally little sense to use the word "null" to describe something other than a null pointer.
Post by Robby
Now, in this function, if this integer is 1 it will do one thing, if
its 2, it will do another and if its 3, it will do even another, but if its
0, it will reset some stuff and do none of the the other things.
As Pavel notes, you want an enum.
Post by Robby
Post by Igor Tandetnik
Post by Robby
which still means 0 right?
I'm not sure I understand this question.
Isn't a void pointer's value 0 ?
I'm not sure what you mean by "the value of a pointer".
Post by Robby
Or should I ask, what is the difference
between a void pointer's value and the value of 0.
The former is of type void*, the latter is of type int.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Barry Schwarz
2010-02-09 13:04:05 UTC
Permalink
On Tue, 9 Feb 2010 00:11:45 -0500, "Igor Tandetnik"
Post by Igor Tandetnik
Post by Robby
Post by Igor Tandetnik
Post by Robby
As you all know, I used to use a non C compliant compiler. Now in the new C
#define NULL 0
Do you have to? NULL should be defined in standard headers that come with any decent C compiler.
#define null 0
I do this because sometimes I have a function's parameter that takes an
integer.
I wouldn't if I were you. You would not use the word "apple" to describe an orange: it makes equally little sense to use the word "null" to
describe something other than a null pointer.
Post by Robby
Now, in this function, if this integer is 1 it will do one thing, if
its 2, it will do another and if its 3, it will do even another, but if its
0, it will reset some stuff and do none of the the other things.
As Pavel notes, you want an enum.
Post by Robby
Post by Igor Tandetnik
Post by Robby
which still means 0 right?
I'm not sure I understand this question.
Isn't a void pointer's value 0 ?
I'm not sure what you mean by "the value of a pointer".
Given ptr, a pointer to any object type, the expression ptr == 0 is
well defined by the language. It will evaluate to true whenever ptr
is a null pointer. However, whether a pointer is a null pointer
depends on its current value, not its type. Given the sequence
void *ptr;
ptr = &ptr;
the expression ptr == 0 is guaranteed to evaluate to false.

But this use of the == operator is a special case in the language. The
fact that a pointer can be compared to 0 in no way implies the
representation of the pointer matches that of an int. Even if the two
objects have the same size, after
int i = 0;
void *p = 0;
i = memcmp(&i, &p, sizeof i);
you still know nothing about the value of i.

Given both of the above, its fair to say the value of a void pointer,
or any other pointer for that matter, is not 0 in the general case. It
is guaranteed to compare to 0 in the specific case using the ==
operator if the pointer has been assigned the null pointer constant
value.
Post by Igor Tandetnik
Post by Robby
Or should I ask, what is the difference
between a void pointer's value and the value of 0.
If the pointer points to an object, the value is guaranteed to be
different from 0.
Post by Igor Tandetnik
The former is of type void*, the latter is of type int.
I wonder if the OP stops at null or maybe goes on to define bool as
float or true as 0. The opportunities to write even more confusing
code are almost boundless.
--
Remove del for email
Robby
2010-02-09 17:20:02 UTC
Permalink
Post by Igor Tandetnik
Post by Robby
I do this because sometimes I have a function's parameter that takes an
integer.
I wouldn't if I were you. You would not use the word "apple" to describe an orange: it makes equally little sense to use the word "null" to describe something other than a null pointer.
Post by Robby
Now, in this function, if this integer is 1 it will do one thing, if
its 2, it will do another and if its 3, it will do even another, but if its
0, it will reset some stuff and do none of the the other things.
As Pavel notes, you want an enum.
Yes, understood, that won't be hard to modify my code.
Post by Igor Tandetnik
Post by Robby
Post by Igor Tandetnik
Post by Robby
which still means 0 right?
I'm not sure I understand this question.
Isn't a void pointer's value 0 ?
I'm not sure what you mean by "the value of a pointer".
Post by Robby
Or should I ask, what is the difference
between a void pointer's value and the value of 0.
The former is of type void*, the latter is of type int.
Looks like I am not the only guy that's confused about this, see:

http://www.lysator.liu.se/c/c-faq/c-1.html

Cheeezzze guys, this could get confusing. I can live with the following
simple explanations as quoted from:

http://www.geekinterview.com/talk/1016-void-pointer-in-c-programming-language.html

["
Void is a non-type which has no size, no format, it is a black hole from
which you cannot read. void * is pointer-to-void.

A void pointer is a pointer which can point to any data type (which of
course requires typecasting). Where as a null pointer is used to indicate
that it is pointing nowhere.

A null pointer is a value that any pointer may take to represent that it is
pointing to "nowhere", while a void pointer is a special type of pointer that
can point to somewhere without a specific type. One refers to the value
stored in the pointer itself and the other to the type of data it points to.
"]

But, where is this "nowhere" ???? "Between you and I, everything points to
something, if it points to a location conataining the value of 0, then lets
say it.

Regards
Robert
Igor Tandetnik
2010-02-09 20:07:15 UTC
Permalink
Post by Robby
But, where is this "nowhere" ????
This is architecture-dependent. Usually a null pointer contains an invalid address (so that trying to dereference it would be caught by the CPU). On most machines, that would be an address of zero. On Windows, for example, lower 64K of address space are reserved and would trigger an access violation if you try to access any location there: this catches most cases where null pointers are misused.
Post by Robby
"Between you and I, everything
points to something
No, not really. There are plenty of addresses in the address space that are not dereferenceable - hence the existence of Access Violation.
Post by Robby
if it points to a location conataining the value
of 0, then lets say it.
It doesn't. A null pointer doesn't point to any valid location, which naturally can't contain any particular value. Just try it:

int* p = NULL;
int x = *p; // see what happens.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Pavel A.
2010-02-10 00:31:59 UTC
Permalink
Post by Igor Tandetnik
A null pointer doesn't point to any valid location, which naturally can't
int* p = NULL;
int x = *p; // see what happens.
There may be a real memory location with adress 0 (either code or data or
both),
so dereferencing "null pointer" may be possible physically - especially
on small microcontrollers like what the OP struggles against.
On most "normal" VM systems, both code and data null locations are
excluded from virtual space of a process, so they cause exception.

.NET has a special nullptr keyword, instead of this controversal 0/NULL
thing.

Regards,
--pa
Igor Tandetnik
2010-02-10 00:52:43 UTC
Permalink
Post by Pavel A.
Post by Igor Tandetnik
A null pointer doesn't point to any valid location, which naturally
int* p = NULL;
int x = *p; // see what happens.
There may be a real memory location with adress 0
Not on Windows.
Post by Pavel A.
so dereferencing "null pointer" may be possible physically -
especially on small microcontrollers like what the OP struggles
against.
That's why I said "architecture-dependent" and "on most machines".

I remember x86 under DOS (real addressing mode, no funny virtual memory business) had its interrupt table at address 0 and up. Writing through a NULL pointer had rather interesting consequences - suddenly, a random memory address became the entry point for some interrupt handler. Single-step debugging was implemented via INT 1, so if you managed to overwrite that, you would disable your debugger, too. Good times.
Post by Pavel A.
.NET has a special nullptr keyword, instead of this controversal
0/NULL thing.
C++0x has this, too, but also, inevitably, supports 0 and NULL for backward compatibility. VS2010 (coming Real Soon Now) implements various parts of C++0x, including nullptr if I recall correctly.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Tim Roberts
2010-02-13 20:18:41 UTC
Permalink
Post by Pavel A.
There may be a real memory location with adress 0 (either code or data or
both),
so dereferencing "null pointer" may be possible physically - especially
on small microcontrollers like what the OP struggles against.
On most "normal" VM systems, both code and data null locations are
excluded from virtual space of a process, so they cause exception.
Yes. NULL is an interesting beast. Although it's literal bit-pattern
value might not be all zeros, the standard requires that a null pointer
BEHAVE in expressions as though it were the integer 0.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Barry Schwarz
2010-02-13 23:39:48 UTC
Permalink
Post by Tim Roberts
Post by Pavel A.
There may be a real memory location with adress 0 (either code or data or
both),
so dereferencing "null pointer" may be possible physically - especially
on small microcontrollers like what the OP struggles against.
On most "normal" VM systems, both code and data null locations are
excluded from virtual space of a process, so they cause exception.
Yes. NULL is an interesting beast. Although it's literal bit-pattern
value might not be all zeros, the standard requires that a null pointer
BEHAVE in expressions as though it were the integer 0.
Not at all. Assuming a prototype for printf in scope,
void *p = 0;
printf("%p\n", p);
would invoke undefined behavior if the null pointer p were to behave
as an int.

A null pointer always behaves like a pointer. The only time it has
any relation to the integer 0 is when it is being assigned the null
pointer constant value 0 or when it is being compared to the null
pointer constant value 0. In the latter case one could loosely argue
the pointer is behaving as an integer but the standard makes it very
clear the integer is behaving as a pointer.
--
Remove del for email
Robby
2010-02-11 14:34:01 UTC
Permalink
Post by Igor Tandetnik
Post by Robby
But, where is this "nowhere" ????
This is architecture-dependent. Usually a null pointer contains an invalid address (so that trying to dereference it would be caught by the CPU). On most machines, that would be an address of zero. On Windows, for example, lower 64K of address space are reserved and would trigger an access violation if you try to access any location there: this catches most cases where null pointers are misused.
Post by Robby
"Between you and I, everything
points to something
No, not really. There are plenty of addresses in the address space that are not dereferenceable - hence the existence of Access Violation.
Post by Robby
if it points to a location conataining the value
of 0, then lets say it.
int* p = NULL;
int x = *p; // see what happens.
That's the under-the-hood explanation I was looking for.
Igor, thankyou very much.

Regards
Roberto
Ulrich Eckhardt
2010-02-09 08:57:15 UTC
Permalink
Post by Robby
Post by Igor Tandetnik
Post by Robby
NULL is a void pointer??
In C, typically, yes.
Post by Robby
which still means 0 right?
I'm not sure I understand this question.
Isn't a void pointer's value 0 ? Or should I ask, what is the difference
between a void pointer's value and the value of 0.
A void pointer doesn't have any type, 'void' is rather a placeholder, but it
does have a value. This value can be null or but it doesn't have to.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Igor Tandetnik
2010-02-09 12:36:45 UTC
Permalink
Post by Ulrich Eckhardt
A void pointer doesn't have any type
This is not true formally, and I don't think it's useful to think this way informally either:
6.2.5p19 The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

The type of a void pointer is, of course, void*.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Ulrich Eckhardt
2010-02-12 08:05:25 UTC
Permalink
Post by Igor Tandetnik
Post by Ulrich Eckhardt
A void pointer doesn't have any type
This is not true formally, and I don't think it's useful to think this way
informally either: 6.2.5p19 The void type comprises an empty set of
values; it is an incomplete type that cannot be completed.
The type defines the behaviour of an instance, all instances of the same
type share similar behaviour. Since void is incomplete, you can never have
any instances of it. An empty set of values means pretty much the same,
that it can't exist.

In that context, calling void a placeholder for the lack of a type is a
reasonable description to me. Agreed, it is not formally true, since the C
standard uses a different meaning, but informally that description is
useful.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Stephan T. Lavavej [MSFT]
2010-02-12 22:06:58 UTC
Permalink
void is an incomplete type and void * is a complete type.

STL
Post by Ulrich Eckhardt
Post by Igor Tandetnik
Post by Ulrich Eckhardt
A void pointer doesn't have any type
This is not true formally, and I don't think it's useful to think this way
informally either: 6.2.5p19 The void type comprises an empty set of
values; it is an incomplete type that cannot be completed.
The type defines the behaviour of an instance, all instances of the same
type share similar behaviour. Since void is incomplete, you can never have
any instances of it. An empty set of values means pretty much the same,
that it can't exist.
In that context, calling void a placeholder for the lack of a type is a
reasonable description to me. Agreed, it is not formally true, since the C
standard uses a different meaning, but informally that description is
useful.
Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Ulrich Eckhardt
2010-02-15 08:54:46 UTC
Permalink
Post by Stephan T. Lavavej [MSFT]
void is an incomplete type and void * is a complete type.
...and your point is what?

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Loading...