((struct name *)0)->b ?

K

karthikbalaguru

Hi,

I find that the program gives the offset of the member of the
structure.
So, probably similar to offsetof() .

But, This is the first time i am seeing the typecast with ' 0' . What
does that mean ?

int main()
{
typedef struct name {
long a;
int b;
long c;
}r;
r re = {3,7,5};

printf("%d",((unsigned int)&(( struct name *)0)->b));

printf("%d",((int)&((struct name *)0)->a));
while(1);
}

The output is 4.

But, What does this ((struct name *)0)->b refer to in the above code.
I tried to print this " ((struct name *)0)->b " alone, but that gave
me errors. :(:(
So, i have raised this query here.

Thx in advans,
Karthik Balaguru
 
A

akappa

But, What does this ((struct name *)0)->b refer to in the above code.
I tried to print this " ((struct name *)0)->b " alone, but that gave
me errors. :(:(

The expression &(( struct name *)0)->b gives the pointer to the
variabile b inside an hypothetical °struct name° that is allocated at
the address 0, if I'm not wrong :)

The expression ((struct name *)0)->b gives you an error because you
are pointing to a memory zone that you aren't supposed to.
 
F

Flash Gordon

akappa wrote, On 19/08/07 18:43:
The expression &(( struct name *)0)->b gives the pointer to the
variabile b inside an hypothetical °struct name° that is allocated at
the address 0, if I'm not wrong :)

You are wrong, in theory at least, because it is a null pointer
constant, and there is no requirement for it to be address 0. In
practice it works like that on many implementations, but it is not
required to.
The expression ((struct name *)0)->b gives you an error because you
are pointing to a memory zone that you aren't supposed to.

The original expression also invoked undefined behaviour, i.e. anything
is allowed to happen, even your tie turning in to an overly friendly
snake. If you don't have a tie it could also cause one to appear around
your neck first!

This is why the implementation is required to provide an offsetof macro.
 
A

akappa

You are wrong, in theory at least, because it is a null pointer
constant, and there is no requirement for it to be address 0. In
practice it works like that on many implementations, but it is not
required to.

Mmh, hence if I do:

*((int*)0)

I'm referencing the NULL pointer and not the memory location at zero
address?
It sounds weird :)
 
F

Flash Gordon

akappa wrote, On 19/08/07 19:00:
Mmh, hence if I do:

*((int*)0)

I'm referencing the NULL pointer and not the memory location at zero
address?
Yes.

It sounds weird :)

That's life.
 
C

Chris Torek

Mmh, hence if I do:

*((int*)0)

I'm referencing the NULL pointer and not the memory location at zero
address?
It sounds weird :)

Possibly. Perhaps they are the same thing (in fact, "usually" they
*are* the same), but possibly they are different.

Imagine, for a moment, that we create a language that looks exactly
the same as Standard C (C89 or C99, either one) except for one big
change. Instead of defining the "null pointer constant" the way C
does it, we add a new keyword, spelled nil, that produces "the null
pointer constant".

In C-- (or whatever this langauge is called), you do not write:

ptr = malloc(n * sizeof *ptr);
if (ptr == NULL) ...

but rather:

ptr = malloc(n * sizeof *ptr);
if (ptr == nil) ...

and if you want to "nil out" a pointer, you write, e.g.:

...
free(ptr);
ptr = nil;

Now, over here on the left, we happen to have a machine where memory
addresses 0x00000000 through 0xbfffffff are all valid, and any
address from 0xc0000000 through 0xffffffff is invalid. (This
machine can therefore use up to 3 GB of memory.)

If you would like your C-- compiler to be able to access all of
memory, you might want to make "nil" come out to 0xc0000000:

ptr = nil; /* compiles to "mov #0xc0000000,ptr" */

Here, *(int *)0 means "get me the bytes at address zero", while
*(int *)nil means "cause a fault because I attempt to dereference
a nil pointer".

Keeping all that in mind, let us "upgrade" from "C--" to regular C.
Now we have to write expressions such as:

ptr = 0; /* perhaps disgused as "ptr = NULL" */

to set "ptr" to the "nil pointer". But a C compiler can -- and in
the distant past, some did -- compile this to the equivalent of
"mov #0xc0000000,ptr". That is, the integer constant 0, used *as*
a pointer, compiles to the machine's most appropriate "nil pointer"
value, whatever that is.

So, C on this particular machine -- if we design the C compiler
so that it can access all memory -- really does attempt to access
location 0xc0000000 (not location 0) when you write:

*(int *)0

To access memory location zero, you simply use something that is
not an "integer constant zero":

int zero_but_not_integer_constant = 0;
int x;

x = *(int *)zero_but_not_integer_constant;

This gives you access to "memory location zero", on this machine,
with this clever C compiler that uses 0xc0000000 for the internal
representation of NULL.

(Again, such systems really did exist once. The original PR1ME
used a special segment for "null pointers", so that they were not
zero. As it turns out, it was so important to run badly-written
C code that *assumed* null pointers were all-zero-bits that they
modified the hardware, adding a whole new instruction -- TCNP, or
"test C null pointer" -- instead of continuing with this approach.
As a C programmer, you may choose whether to assume that future
systems will be forced to accomodate your bad C code, as PR1ME had
to, or whether to write *good* C code that will work even on "weird"
machines.)

(Note that if you are writing "inherently machine dependent code",
such as code to handle the bootstrap sequence on some particular
machine, it is probably pretty safe to make machine-dependent
assumptions. After all, the code that makes the Zorgblatt 15 boot
is probably not going to work at all on the Frobley 71, no matter
how portable you try to make it. There are cases where *some* of
the boot code can be shared, though -- so you might want to write
the "shareable" part in a portable way, and the machine-dependent
part in "whatever way works".)
 

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

Forum statistics

Threads
473,772
Messages
2,569,591
Members
45,100
Latest member
MelodeeFaj
Top