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

question about NULL pointer and address 0x00000h

24 views
Skip to first unread message

hingwah

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
in C,the NULL is defined as (void *)(0)

however,what if I really need to access 0x0000h to access the vector
table for some system programming?

-hs-

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
hingwah <5019...@uxmail.cityu.edu.hk> a écrit dans le message
<390D7237...@uxmail.cityu.edu.hk>...

>in C,the NULL is defined as (void *)(0)
>
>however,what if I really need to access 0x0000h to access the vector
>table for some system programming?


No way in standard C, because it is compiler dependant.

It can be
void *p=0;
or
void *p=0L;
or
void *p=NULL;
or
void *p=(void*)0;
or
unsigned long n=0L;
void *p=(void*)n;
or
p=MK_FP(0,0);
or whatever.
--
-hs- "Stove"
CLC-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
ISO-C Library: http://www.dinkum.com/htm_cl
"Really? When run on my machine, a printed copy of the C FAQ leaps
from the monitor and whacks me over the head.." -- Chris Mears CLC


Richard Bos

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
hingwah <5019...@uxmail.cityu.edu.hk> wrote:

> in C,the NULL is defined as (void *)(0)

Or simple, unadorned 0. Or compile-time expression that evaluates as
such.

> however,what if I really need to access 0x0000h to access the vector
> table for some system programming?

You can't. Perhaps your compiler lets you, in a compiler-specific way,
but then you would need to ask in a newsgroup for that compiler.

You _might_ try the following:

int zero=0;
void *pointer=zero;

which _could_ work, because compile-time 0 does not necessarily equal
run-time 0x0000, but run-time 0 does. Behaviour following this is
undefined, however.
Do read the FAQ, btw, which explains all this better than I ever will:
<http://www.eskimo.com/~scs/C-faq/s5.html>.

Richard

Gordon Burditt

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
>in C,the NULL is defined as (void *)(0)
>
>however,what if I really need to access 0x0000h to access the vector
>table for some system programming?

Then you do so in an unportable manner, or not at all.
Dereferencing NULL might access/scribble on the vector table,
as the implementation's definition of undefined behavior.

It is also possible that the vector table is not in your
memory map and you can't access it at all. (Even in
MS-DOS, dereferencing a small-memory-model NULL does not
access the vector table.) UNIX and even Windows are
more likely to leave it out of the map.

Gordon L. Burditt

mike burrell

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
hingwah <5019...@uxmail.cityu.edu.hk> wrote:
> in C,the NULL is defined as (void *)(0)

> however,what if I really need to access 0x0000h to access the vector
> table for some system programming?

void *special_pointer;

memset(&special_pointer, 0, sizeof special_pointer);

--
/"\ m i k e b u r r e l l
\ / ASCII RIBBON CAMPAIGN mik...@home.com
X AGAINST HTML MAIL
/ \

Kaz Kylheku

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
On Mon, 01 May 2000 20:01:59 +0800, hingwah <5019...@uxmail.cityu.edu.hk>

wrote:
>in C,the NULL is defined as (void *)(0)

Wrong; in your compiler's header files, NULL may be declared that way. ANSI C
says that the macro NULL expands to an implementation-defined null pointer
constant.

ANSI C also says that a null pointer constant is one of two things:
a constant integral expression having the value zero, or such an
expression cast to (void *).

>however,what if I really need to access 0x0000h to access the vector
>table for some system programming?

If you wanted to access the system vector table, you would no longer be
programming in standard C. You would be relying on features of the C
implemenation and and of the execution environment, which are undoubtedly
described in some kind of documentation about that C implementation and that
execution environment.

In many C implementations, the null pointer corresponds to address zero, so
that you can use a null pointer as address zero when needed.

If you specifically want an implementation-defined conversion from the int
value 0 rather than a null pointer, then what you should do is convert
an int zero value that is not a constant expression. For example:

/*...*/


char *zeroaddr = (char *) 0, 0;

In C, the comma operator is not considered a constant expression, so this
declaration does not portably create a null pointer but rather a pointer with
an implementation defined pointer value.

Of course, there is no guarantee that this value references a vector table, or
address zero or any such thing. It doesn't make a whole lot of sense to try to
do something inherently non-portable in a portable way.

--
#exclude <windows.h>

Chris Torek

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
In article <slrn8grcc...@ashi.FootPrints.net>

Kaz Kylheku <k...@ashi.footprints.net> writes:
>If you wanted to access the system vector table, you would no longer be
>programming in standard C. You would be relying on features of the C
>implemenation and and of the execution environment ...

Or, to put it another way, you must abandon (perhaps just temporarily)
the ANSI C standard and all its guarantees. You must risk un- or
implementation-defined behavior. Your reward for taking this risk
is that you can -- assuming you get it right, and your implementation
cooperates, or at least stays out of the way -- in fact access the
system vector table.

Clearly, the reward -- being able to write the program you must
write -- is worth the risk (which is that your program might not
work). If the "risk" fails, you have a program that does not do
what you want it to do; but if you attempt to write in strictly
conformant ANSI C, you also have a program that does not do what
you want it to do. There is no downside to leaving ANSI C behind.

This same sort of risk/reward analysis holds for *any* departure
from ANSI C, even something as simple as "I want to clear the
screen". If you absolutely positively HAVE to clear the screen,
you cannot do it in ANSI C, so you must risk using some nonstandard
extension, and having your program fail on some other system, where
that extension does not exist or does not work or whatever. If
you can stand the idea of *not* having your program clear the
screen, though, your reward may be a program that "just works" on
a new system you never thought you would be using.

Compare this with "void main": here you take an admittedly small
risk -- "void main" often works -- but your reward is ... nothing
at all. Your program will work at least as well if you write "int
main" instead. Might as well write strictly conforming code; there
is no risk, and the reward is that your program is guaranteed to
work (provided the rest of it is also conformant).

>If you specifically want an implementation-defined conversion from the int
>value 0 rather than a null pointer, then what you should do is convert
>an int zero value that is not a constant expression. For example:
>

> char *zeroaddr = (char *) 0, 0;
>
>In C, the comma operator is not considered a constant expression, so this
>declaration does not portably create a null pointer but rather a pointer with
>an implementation defined pointer value.

I think you wanted:

char *zeroaddr = (char *)(0, 0);

since the above parses the same as:

char *zeroaddr = ((char *)0), 0;

which should draw a diagnostic.

>Of course, there is no guarantee that this value references a vector
>table, or address zero or any such thing. It doesn't make a whole lot
>of sense to try to do something inherently non-portable in a portable way.

Indeed.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.

Mark McIntyre

unread,
May 1, 2000, 3:00:00 AM5/1/00
to
On Mon, 01 May 2000 20:01:59 +0800, hingwah
<5019...@uxmail.cityu.edu.hk> wrote:

>in C,the NULL is defined as (void *)(0)

Or zero. Implementation defined.

>however,what if I really need to access 0x0000h to access the vector
>table for some system programming?

Who says that its there? or htat your OS has one?

This is an OS dependent question. On any system I've ever used,
attempting to read address 0 in other than kernel mode caused instant
program death.


Mark McIntyre

C- FAQ: http://www.eskimo.com/~scs/C-faq/top.html

Steve Summit

unread,
May 6, 2000, 3:00:00 AM5/6/00
to
In article <390d8002...@news.worldonline.nl>, r...@fdhoekstra.nl
(Richard Bos) writes:

> hingwah <5019...@uxmail.cityu.edu.hk> wrote:
>> however,what if I really need to access 0x0000h to access the vector
>> table for some system programming?
>
> You _might_ try the following:
> int zero=0;
> void *pointer=zero;
> which _could_ work...

Well, if we're going to underline the "might" and the "could",
he _could_ also try

int *pointer = 0;

That'll probably work, too. And, for this kind of code,
"probably" tends to be good enough, because it's not as if the
function for accessing a particular machine's interrupt table
(which is just about 100% system-specific, on its face) has to
be maximally portable.

> Do read the FAQ, btw, which explains all this better than I ever will:
> <http://www.eskimo.com/~scs/C-faq/s5.html>.

Actually, the book version has hingwah's very question in it:

5.19: How can I access an interrupt vector located at the machine's
location 0? If I set a pointer to 0, the compiler might
translate it to some nonzero internal null pointer value.

A: Since whatever is at location 0 is obviously machine dependent,
you're free to use whatever machine-dependent trick will work
to get there. Read your vendor's documentation (and see chapter
19). It's likely that if it's at all meaningful for you to be
accessing location 0, the system will be set up to make it
reasonably easy to do so. Some possibilities are:

1. Simply set a pointer to 0. (This is the way that doesn't
have to work, but if it's meaningful, it probably will.)

2. Assign the integer 0 to an int variable, and convert that
int to a pointer. (This is also not guaranteed to work,
but it probably will.)

3. Use a union to set the bits of a pointer variable to 0:

union {
int *u_p;
int u_i; /* assumes sizeof(int) >= sizeof(int *) */
} p;

p.u_i = 0;

4. Use memset() to set the bits of a pointer variable to 0:

memset((void *)&p, 0, sizeof(p));

5. Declare an external variable or array

extern int location0;

and use an assembly language file, or some special
linker invocation, to arrange that this symbol refers
to (i.e. the variable is placed at) address 0.

See also questions 4.14 and 19.25.

References: K&R1 Sec. A14.4 p. 210
K&R2 Sec. A6.6 p. 199
ANSI Sec. 3.3.4
ISO Sec. 6.3.4
Rationale Sec. 3.3.4
H&S Sec. 6.2.7 pp. 171-2

Steve Summit
s...@eskimo.com

Morris M. Keesan

unread,
May 8, 2000, 3:00:00 AM5/8/00
to
On Mon, 01 May 2000 23:23:03 +0100, Mark McIntyre
<ma...@garthorn.demon.co.uk> wrote:
>On Mon, 01 May 2000 20:01:59 +0800, hingwah
><5019...@uxmail.cityu.edu.hk> wrote:
>
>>in C,the NULL is defined as (void *)(0)
>
>Or zero. Implementation defined.
>
>>however,what if I really need to access 0x0000h to access the vector
>>table for some system programming?
>
>Who says that its there? or htat your OS has one?
>
>This is an OS dependent question. On any system I've ever used,
>attempting to read address 0 in other than kernel mode caused instant
>program death.

In Berkeley Unix (3.x BSD and 4.x BSD, at least), there was a (readable)
word of all zero bits at location 0 of the user address space. This led to
several generations of graduate students who didn't understand the
difference between NULL and "".
--
Morris M. Keesan -- mke...@kenan.com
Kenan Systems Corp., a wholly-owned subsidiary of Lucent Technologies

glen herrmannsfeldt

unread,
May 8, 2000, 3:00:00 AM5/8/00
to
s...@eskimo.com (Steve Summit) writes:

>(Richard Bos) writes:
>> hingwah <5019...@uxmail.cityu.edu.hk> wrote:

>>> however,what if I really need to access 0x0000h to access the vector
>>> table for some system programming?
>>

>> You _might_ try the following:
>> int zero=0;
>> void *pointer=zero;
>> which _could_ work...

>Well, if we're going to underline the "might" and the "could",
>he _could_ also try

> int *pointer = 0;

Note that intel hardware specifically allows/requires the NULL pointer
to have the binary value 0. The segment selector 0 is specifically
reserved as the null segment selector. If you are running in protected mode
you will need a segment selector allocated to the part of memory you want,
even if it is real address 0. Memory management can move addresses
around, too.

-- glen

Mark McIntyre

unread,
May 8, 2000, 3:00:00 AM5/8/00
to
On 8 May 2000 19:57:48 GMT, g...@ugcs.caltech.edu (glen herrmannsfeldt)
wrote:

Uh, first of all whats this got to do with ANSI C (all this stuff
about segments etc) and secondly, in protected mode there _are_ no
segments... Its flat memory...

--

Gordon Burditt

unread,
May 11, 2000, 3:00:00 AM5/11/00
to
>>Note that intel hardware specifically allows/requires the NULL pointer
>>to have the binary value 0. The segment selector 0 is specifically
>>reserved as the null segment selector. If you are running in protected mode
>>you will need a segment selector allocated to the part of memory you want,
>>even if it is real address 0. Memory management can move addresses
>>around, too.
>
>Uh, first of all whats this got to do with ANSI C (all this stuff
>about segments etc) and secondly, in protected mode there _are_ no
>segments... Its flat memory...

On the Intel [3456]86, there is a huge-model 32-bit memory model.
Pointers are 48 bits, including 16 bits of segment register.
I'm sure it will be popular in a few years when most Windows
programs won't fit in a virtual address space of 4GB each
for code, data, copyright notices, and license agreements.

Gordon L. Burditt

0 new messages