Memory allignment/type casting question

M

MisterE

What happens when you type cast like this:

(note this is code i just typed cause I dont have a compiler ATM):
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char*argv[])
{
unsigned char c[] = {0,1,2,3,4,5,6,7,8,9,10};
unsigned int *i1, *i2, *i3;

i1 = &c[0];
i2 = &c[1];
i3 = &c[2];

printf("%x %x %x",*i1,*i2,*i3);
return 0;
}

What output will be printed? I have noticed that some some systems require
integers to be from alligned address etc. others don't. One system has bytes
in i2 and i3 that are not part of c array at all (ie outputting things like
0xFF01 0xFE02 0xFF03)

Is the behavoir defined in anyway at all for anything? Or should the value
of the whole integer be undefined?

The reason I ask this is I have to port some craptastic code that has
pointers of different types randomly pointing to position in an array of
chars... and as you would expect its behaves differently on every compiler.
 
I

Ian Collins

MisterE said:
What happens when you type cast like this:

(note this is code i just typed cause I dont have a compiler ATM):
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char*argv[])
{
unsigned char c[] = {0,1,2,3,4,5,6,7,8,9,10};
unsigned int *i1, *i2, *i3;

i1 = &c[0];
i2 = &c[1];
i3 = &c[2];
None of those should compile without a cast.
printf("%x %x %x",*i1,*i2,*i3);
return 0;
}

What output will be printed? I have noticed that some some systems require
integers to be from alligned address etc. others don't. One system has bytes
in i2 and i3 that are not part of c array at all (ie outputting things like
0xFF01 0xFE02 0xFF03)

Is the behavoir defined in anyway at all for anything? Or should the value
of the whole integer be undefined?
No, it is totally platform specific.
The reason I ask this is I have to port some craptastic code that has
pointers of different types randomly pointing to position in an array of
chars... and as you would expect its behaves differently on every compiler.
Good luck, you'll probably need it.
 
B

baichuan0698

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

int main (int argc, char*argv[])
{
unsigned char c[] = {0,1,2,3,4,5,6,7,8,9,10};
unsigned int *i1, *i2, *i3;


i1 = (unsigned int *)&c[0];
i2 = (unsigned int *)&c[1];
i3 = (unsigned int *)&c[2];


printf("0x%06x 0x%06x 0x%06x",i1,i2,i3);

system("PAUSE");
return 0;
}
 
V

vippstar

Is the behavoir defined in anyway at all for anything? Or should the value
of the whole integer be undefined?
UB.

The reason I ask this is I have to port some craptastic code that has
pointers of different types randomly pointing to position in an array of
chars... and as you would expect its behaves differently on every compiler.

Great, then you don't care you invoke undefined behavior, you just
want it to work under certain compilers.
Why do you post in comp.lang.c? It'd be more appropriate to ask in
each and every implementation group about how you'd make such code
generate the desired output.
 
J

James Kuyper

MisterE said:
What happens when you type cast like this:

Your sample code doesn't have any type casts. It should, but it doesn't.
(note this is code i just typed cause I dont have a compiler ATM):
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char*argv[])
{
unsigned char c[] = {0,1,2,3,4,5,6,7,8,9,10};
unsigned int *i1, *i2, *i3;

i1 = &c[0];
i2 = &c[1];
i3 = &c[2];

Those assignments require the type casts that you mentioned, but did not
provide. Without them there is a constraint violation (6.5.16.1p1).

If you add (unsigned*) before the '&' in each of those statements,
you'll get an implementation-defined result whose meaning is not
specified in any way by the C standard. If the alignment requirement of
unsigned is any number greater than 1, then the behavior of that
conversion is undefined for at least one of those statements.
printf("%x %x %x",*i1,*i2,*i3);

Even if the conversions themselves did not cause something awful to
happen, the standard does not define where the resulting pointer points,
or even whether it points at any valid location, so the behavior of the
expressions "*i1", "*i2" and "*i3" would also be undefined for that reason.

Even if those pointers do point into the array 'c', the behavior is
still undefined, because you're accessing the memory through an lvalue
of a type that isn't compatible with the effective type of the object
stored in that location.

In practice, for an implementations without alignment restrictions on
unsigned int, the result should be to interpret the appropriate bytes of
'c' as if they were unsigned int. However, you should never write code
that is intended to be even remotely portable, which makes such assumptions.
return 0;
}

What output will be printed? I have noticed that some some systems require
integers to be from alligned address etc. others don't. One system has bytes
in i2 and i3 that are not part of c array at all (ie outputting things like
0xFF01 0xFE02 0xFF03)

Since the behavior is undefined, in principle an implementation can
print just about anything at this point. In practice, I would not have
expected that result. Perhaps if you identify the compiler, the
operating system, and the CPU, someone else can give you a better
explanation for those results than I can.
Is the behavoir defined in anyway at all for anything? Or should the value
of the whole integer be undefined?

No. The behavior of your entire program is undefined, not just the value
of the integer.
The reason I ask this is I have to port some craptastic code that has
pointers of different types randomly pointing to position in an array of
chars... and as you would expect its behaves differently on every compiler.

Lovely! The positions are probably not as random as they seem; otherwise
it wouldn't even work on one compiler (I assume that there is at least
one compiler where it actually works?).
 
J

James Kuyper

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

int main (int argc, char*argv[])
{
unsigned char c[] = {0,1,2,3,4,5,6,7,8,9,10};
unsigned int *i1, *i2, *i3;


i1 = (unsigned int *)&c[0];
i2 = (unsigned int *)&c[1];
i3 = (unsigned int *)&c[2];


printf("0x%06x 0x%06x 0x%06x",i1,i2,i3);

system("PAUSE");

That is a gratuitously unportable piece of code. 'PAUSE' might not even
be supported by system() on the OP's machine; it's not supported on any
machine I program on. Even if it is supported, it might not do what you
expect it to do.
 
C

CBFalconer

MisterE said:
What happens when you type cast like this:

(note this is code i just typed cause I dont have a compiler ATM):
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char*argv[]) {
unsigned char c[] = {0,1,2,3,4,5,6,7,8,9,10};
unsigned int *i1, *i2, *i3;

i1 = &c[0];
i2 = &c[1];
i3 = &c[2];

printf("%x %x %x",*i1,*i2,*i3);
return 0;
}

What output will be printed? I have noticed that some some systems
require integers to be from alligned address etc. others don't. One
system has bytes in i2 and i3 that are not part of c array at all
(ie outputting things like 0xFF01 0xFE02 0xFF03)

If any. Depending on system, the values in i2 and i3 are probably
illegal int pointers, and anything can happen. The assignments to
them should have generated compilation errors.
 

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,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top