16 bit pointer typecast on 16 bit system

  • Thread starter Christian Wittrock
  • Start date
C

Christian Wittrock

Hi,

What does ANSI C say about casting an 8 bit pointer to a 16 bit one,
when the byte pointer is pointing to an odd address? I have detected a
problem in the Samsung CalmShine 16 compiler. This compiler I use for
the Samsung 16 bit Smartcard chips and I want to know if it is
compliant with the ANSI standard or if it violates it.

Have a look at this super simple example, where the value of b is
incorrect:

#include <stdio.h>

// Define an array in the EEPROM memory at address 0x081000
char data[8]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} _at_
0x81000, eeprom;

int main ( void )
{
char a;
short b;
long c;
char* bpData;

// Set up the pointer to point to an odd address
bpData = &data[1];

// read a byte from an even address
a= *(bpData + 1);

// Read a word from an odd address. This causes problems. Instead of
// getting 0x0102 I get 0x001. What does ANSI C say about this?
b= *(short*)(bpData) ;

// just to check the value of the pointer, if the value of it is to
be stored in a variable
c= (long)bpData;

return 0x0 ;
}
 
M

michaelquinlivan

yes, you should get 0x102 (if it is Big-endian) or 0x201 (if it is
Little-endian) but definitely not 0x1.

I've confirned this with the following test program in gcc:

#include <stdio.h>
char a[] = {0,1,2,3,4};
short b;
int main()
{
b = *(short *)(a+1);
printf("b = 0x%x\n",b);
return 0;
}

It prints the result "b = 0x201" (on an x86, which is little-endian).
I'd say that your compiler is broken...

MQ.
 
C

Chris Dollin

yes, you should get 0x102 (if it is Big-endian) or 0x201 (if it is
Little-endian) but definitely not 0x1.

I've confirned this with the following test program in gcc:

#include <stdio.h>
char a[] = {0,1,2,3,4};
short b;
int main()
{
b = *(short *)(a+1);
printf("b = 0x%x\n",b);
return 0;
}

It prints the result "b = 0x201" (on an x86, which is little-endian).
I'd say that your compiler is broken...

I'd say your expectations are broken.

You take a value that isn't and never has been pointer-to-short, forcibly
convert it to pointer-to-short, and dereference it -- that sounds to me
like it would generate undefined behaviour.
 
D

Dik T. Winter

> char* bpData; ....
> bpData = &data[1]; ....
> // Read a word from an odd address. This causes problems. Instead of
> // getting 0x0102 I get 0x001. What does ANSI C say about this?
> b= *(short*)(bpData) ;

Undefined behaviour.
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

Christian said:
Hi,

What does ANSI C say about casting an 8 bit pointer to a 16 bit one,
when the byte pointer is pointing to an odd address? I have detected a
problem in the Samsung CalmShine 16 compiler. This compiler I use for
the Samsung 16 bit Smartcard chips and I want to know if it is
compliant with the ANSI standard or if it violates it.

Have a look at this super simple example, where the value of b is
incorrect:

#include <stdio.h>

// Define an array in the EEPROM memory at address 0x081000
char data[8]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} _at_
0x81000, eeprom;

int main ( void )
{
char a;
short b;
long c;
char* bpData;

// Set up the pointer to point to an odd address
bpData = &data[1];

// read a byte from an even address
a= *(bpData + 1);

// Read a word from an odd address. This causes problems. Instead of
// getting 0x0102 I get 0x001. What does ANSI C say about this?
b= *(short*)(bpData) ;
It might cause a trap.
Or something else undefined could happen.

Just assemble the bytes the way you need them.
Assuming you have 8 bit chars,
a = bpData[0] << 8 & bpData[1];

(make the types unsigned btw.)
 
C

Christian Wittrock

Hi All,

thanks for the feedback. I am not looking for solutions on how to code
this using byte operations only. The question is related to what the
ANSI C standard has to say about the behaviour when typecasting in a 16
bit (or 32/64 for that matter) processor.

Logically, then any code written in ANSI should be compilable for any
platform and run without problems (in theory ;-) ). And this example is
in ANSI C. But standards only go so far and there are always "holes"
where a certain behaviour is not mentioned or dealt with. Since I can't
remember all of the ANSI C standard....... :-(

The type cast comes in place to be able to traverse through incomming
data on a I/O interface. The data is formattet in TLV format (Tag,
Length, Value). That means that I can never be sure that a word is
located on an aligned address. I use the byte pointer as I only have
the need for one pointer (this is a highly embedded system so I only
create variables and pointers if they are needed). Then, if I have to
retrieve a word I typecast.

The processor in question is a pure 16 bit one. That means it always
read 16 bytes from a memory location and throws away any unwanted part.

Thanks,
Christian
 
C

Chris Dollin

Christian said:
Hi All,

thanks for the feedback. I am not looking for solutions on how to code
this using byte operations only. The question is related to what the
ANSI C standard has to say about the behaviour when typecasting in a 16
bit (or 32/64 for that matter) processor.

Logically, then any code written in ANSI should be compilable for any
platform and run without problems (in theory ;-) ).

Not in theory, and not in practice.

The standard says what's allowable and what's required. "What's required"
is surprisingly limited: a compiler must generate diagnostics for
constraint violations, an implementation must permit items of various
minimal sizes, stuff like that. An implementation can run out of
resources and die at the drop of a hat (but not at the drop of a mere
cap).

But conforming to the standard is your best bet of writing portable
code, if that's what you're trying to write.
The type cast comes in place to be able to traverse through incomming
data on a I/O interface. The data is formattet in TLV format (Tag,
Length, Value). That means that I can never be sure that a word is
located on an aligned address. I use the byte pointer as I only have
the need for one pointer (this is a highly embedded system so I only
create variables and pointers if they are needed). Then, if I have to
retrieve a word I typecast.

You have a choice.

(a) either arrange always to use the same implementation and ensure
that it's document to do what you want. Since you're on some
embedded system, that might be a plausible tactic.

(b) Don't use casts that way: it's not portable. Do the right thing
instead: something like `p[0] + (p[1] << PROBABLYEIGHT)`. Of
course if the generated code for this is awful and it matters,
you may be stuck with (a).
The processor in question is a pure 16 bit one. That means it always
read 16 bytes from a memory location and throws away any unwanted part.

The Standard doesn't exhibit this much interest in implementation
detail. (And "any unwanted part" is interestingly ambiguous.)
 
J

Jack Klein

Hi,

What does ANSI C say about casting an 8 bit pointer to a 16 bit one,

The C standard says nothing at all about "8 bit pointers" and "16 bit
pointers". It talks about pointers to types, and those types can have
different sizes on different implementations. But we'll assume for
the moment that you know that characters have 8 bits and shorts 16
bits on your platform.
when the byte pointer is pointing to an odd address? I have detected a
problem in the Samsung CalmShine 16 compiler. This compiler I use for
the Samsung 16 bit Smartcard chips and I want to know if it is
compliant with the ANSI standard or if it violates it.

The C standard says that the behavior is undefined.
Have a look at this super simple example, where the value of b is
incorrect:

#include <stdio.h>

// Define an array in the EEPROM memory at address 0x081000
char data[8]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} _at_
0x81000, eeprom;

Actually the minute you use the non-standard extension "_at_ 0x81000,
eprom", you have left the realm of the C standard behind. This means
nothing at all in standard C.

But assuming this results in a valid pointer to char...
int main ( void )
{
char a;
short b;
long c;
char* bpData;

// Set up the pointer to point to an odd address
bpData = &data[1];

If the non-standard definition does indeed create an array of chars
that your program has the right to access, this is a valid assignment
and places the address value 0x81000 in bpData.

But notice that you could have replaced the two lines with a simple
initialization in the definition of the pointer:

char *bpData = data + 1;
// read a byte from an even address
a= *(bpData + 1);

This is perfectly legal code, and assigned the contents of the char at
0x81002 to 'a'.
// Read a word from an odd address. This causes problems. Instead of
// getting 0x0102 I get 0x001. What does ANSI C say about this?
b= *(short*)(bpData) ;

The C standard says that if you use a pointer to something other than
a character type to access something, and the object does not have the
type of the pointer, the behavior is undefined.

C also says that when you convert pointer types, as your conversion
using a cast above, the result is undefined if the pointer is not
properly aligned for the new type.

I assume this is either a 16 or 32 bit processor, DSP, or
microcontroller. Some of these do have alignment requirements, and
accessing a 16-bit value on an odd address will violate these. The
results include a value that you consider "wrong", to generating a
hardware exception. An ARM, for example, will generate an address
abort.

Have you read the documentation on the processor, DSP, or
microcontroller that you are using? What are its address alignment
requirements?
// just to check the value of the pointer, if the value of it is to
be stored in a variable
c= (long)bpData;

return 0x0 ;
}

Someone who programs embedded systems in C, using architectures
dissimilar to typical desk top processors, needs to know a fair bit
more the C standard, especially if you try to do things like pointer
punning.
 
K

Keith Thompson

Christian Wittrock said:
thanks for the feedback. I am not looking for solutions on how to code
this using byte operations only. The question is related to what the
ANSI C standard has to say about the behaviour when typecasting in a 16
bit (or 32/64 for that matter) processor.

Please provide some context when you post a followup. Google now
makes this reasonably easy to do, but you still need to trim anything
that's not relevant.
Logically, then any code written in ANSI should be compilable for any
platform and run without problems (in theory ;-) ).
Nope.

[snip]

The type cast comes in place to be able to traverse through incomming
data on a I/O interface. The data is formattet in TLV format (Tag,
Length, Value). That means that I can never be sure that a word is
located on an aligned address. I use the byte pointer as I only have
the need for one pointer (this is a highly embedded system so I only
create variables and pointers if they are needed). Then, if I have to
retrieve a word I typecast.

The processor in question is a pure 16 bit one. That means it always
read 16 bytes from a memory location and throws away any unwanted part.

You mean 16 bits, not 16 bytes, right?

Let's assume char is 8 bits and short is 16 bits. You have a 16-bit
short value stored in an array of char, and you can't guarantee that
it's aligned properly. If you attempt to read it directly as a short,
you'll invoke undefined behavior; on many real-world systems, it will
cause your program to crash.

The simplest way to extract data from a byte array is to use memcpy().
Since it (theoretically) copies a byte at a time, alignment won't be
an issue. If you copy the data into a declared object of type short,
the target is guaranteed to be aligned probably.

I'm assuming that byte order isn't an issue (e.g., that the short was
written into the byte array by the current program, or at least on the
current system). If that's not the case, you'll need to deal with
that; memcpy() won't do it for you.
 
C

Christian Wittrock

** SIGH ***

Your answer start out professionally but end as "I know all and you
know nothing"! Please do not post any replies if you do not have
respect for people.

I had assumed that people would disregard the EEPROM variable as the
question is not related to this. I did not explicitly write what
alignment the processor uses, as this is implicitly given in the
example. And again the alignment (odd or even) is not that relevant.
The question was in relation to pointer casting behaviour when
accessing non-aligned memory locations. Shall a compiler automatically
do the trick for you to be ANSI compliant or not. And excuse me for not
knowing the standard by heart.

The reason why I posted my question was because I was faced with the
claim that the compiler (in question) is not ANSI C compliant. First of
all I always retrieve 16 bit values( or larger) on systems like this
one by getting a single byte at a time (the code has to be platform
independant). But again, that was not the question. The question is the
casting and not whether this a the correct way to code.

For someone who claims to be an expert and who talks down to others, I
would expect a bit more insigth than this. And it not good practise to
initialise variables within the declaration. Keep in mind that quite a
few embedded systems are put into a ROM chip, thereby creating the need
for a patch system. To initialize variables in the declaration will
make the compiler put in code before you can do a call to the patch
system.

I apologize for this angry reply, but I just got p***** off. You should
repect others more and answer any post in a professional way.

/Christian




Jack Klein skrev:
Hi,

What does ANSI C say about casting an 8 bit pointer to a 16 bit one,

The C standard says nothing at all about "8 bit pointers" and "16 bit
pointers". It talks about pointers to types, and those types can have
different sizes on different implementations. But we'll assume for
the moment that you know that characters have 8 bits and shorts 16
bits on your platform.
when the byte pointer is pointing to an odd address? I have detected a
problem in the Samsung CalmShine 16 compiler. This compiler I use for
the Samsung 16 bit Smartcard chips and I want to know if it is
compliant with the ANSI standard or if it violates it.

The C standard says that the behavior is undefined.
Have a look at this super simple example, where the value of b is
incorrect:

#include <stdio.h>

// Define an array in the EEPROM memory at address 0x081000
char data[8]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} _at_
0x81000, eeprom;

Actually the minute you use the non-standard extension "_at_ 0x81000,
eprom", you have left the realm of the C standard behind. This means
nothing at all in standard C.

But assuming this results in a valid pointer to char...
int main ( void )
{
char a;
short b;
long c;
char* bpData;

// Set up the pointer to point to an odd address
bpData = &data[1];

If the non-standard definition does indeed create an array of chars
that your program has the right to access, this is a valid assignment
and places the address value 0x81000 in bpData.

But notice that you could have replaced the two lines with a simple
initialization in the definition of the pointer:

char *bpData = data + 1;
// read a byte from an even address
a= *(bpData + 1);

This is perfectly legal code, and assigned the contents of the char at
0x81002 to 'a'.
// Read a word from an odd address. This causes problems. Instead of
// getting 0x0102 I get 0x001. What does ANSI C say about this?
b= *(short*)(bpData) ;

The C standard says that if you use a pointer to something other than
a character type to access something, and the object does not have the
type of the pointer, the behavior is undefined.

C also says that when you convert pointer types, as your conversion
using a cast above, the result is undefined if the pointer is not
properly aligned for the new type.

I assume this is either a 16 or 32 bit processor, DSP, or
microcontroller. Some of these do have alignment requirements, and
accessing a 16-bit value on an odd address will violate these. The
results include a value that you consider "wrong", to generating a
hardware exception. An ARM, for example, will generate an address
abort.

Have you read the documentation on the processor, DSP, or
microcontroller that you are using? What are its address alignment
requirements?
// just to check the value of the pointer, if the value of it is to
be stored in a variable
c= (long)bpData;

return 0x0 ;
}

Someone who programs embedded systems in C, using architectures
dissimilar to typical desk top processors, needs to know a fair bit
more the C standard, especially if you try to do things like pointer
punning.
 
F

Flash Gordon

Christian said:
** SIGH ***

Your answer start out professionally but end as "I know all and you
know nothing"! Please do not post any replies if you do not have
respect for people.

At least Jack's message starts out professionally. Had you paid a little
attention to this group you would know that top posting is not
considered to be acceptable here. Your reply belongs after the parts of
the post you are responding to, not above it.

If you think Jack's response was impolite, I suggest that Usenet is not
the place for you. His reply was fairly mild.
I had assumed that people would disregard the EEPROM variable as the
question is not related to this.

If we don't know what it does, how can we know if it is relevant or not?
> I did not explicitly write what
alignment the processor uses, as this is implicitly given in the
example. And again the alignment (odd or even) is not that relevant.

When doing type punning with pointers alignment is highly relevant.

For someone who claims to be an expert and who talks down to others, I
would expect a bit more insigth than this. And it not good practise to
initialise variables within the declaration. Keep in mind that quite a
few embedded systems are put into a ROM chip, thereby creating the need
for a patch system. To initialize variables in the declaration will
make the compiler put in code before you can do a call to the patch
system.

Well, as Jack pointed out, you invoke undefined behaviour by casting a
pointer to another pointer type if it is not alligned correctly for the
type you are casting it to. Therefore anything can happen, including you
getting the result you are seeing or everyone taking an instant dislike
to you. Undefined behaviour means the behaviour is undefined.
I apologize for this angry reply, but I just got p***** off. You should
repect others more and answer any post in a professional way.

The correct approach is to not actually post if you feel a need to
apologise for the post in the post. Jack's reply gave you a reasonably
detailed description of why the code you wrote could fail, and correctly
suggested that you should have read the documentation about your
implementation so you know how it works.


The above is not insulting, it just points out that you need to know a
fair bit.
 
K

Kenny McCormack

** SIGH ***

Your answer start out professionally but end as "I know all and you
know nothing"! Please do not post any replies if you do not have
respect for people.

Chris, this is clc. You'll get used to it after a while. You might even
come to like it. After all, half a dozen "regulars", about as many
"trolls", and an uncountable number of newbies can't be wrong.

Useful clc-related links:

http://en.wikipedia.org/wiki/Clique
http://en.wikipedia.org/wiki/Aspergers
http://en.wikipedia.org/wiki/C_programming_language
 
M

Mark McIntyre

** SIGH ***

Your answer start out professionally but end as "I know all and you
know nothing"!

Actually, Jack's message did nothing of the sort. If you can't take
criticism of your code, then you need to get a different job.
Please do not post any replies if you do not have
respect for people.

The R-word again. Its worth bearing in mind that you don't
automatically get respect, you have to earn it. By posting the reply
I'm commenting on, your account is going into debit.
And excuse me for not knowing the standard by heart.

Of course.

Note however that you did get an answer to your question, and not one
which insulted you. Any percieved insult was entirely in your mind.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
O

Old Wolf

Christian said:
This compiler I use for
the Samsung 16 bit Smartcard chips and I want to know if it is
compliant with the ANSI standard or if it violates it.

I see you got a bunch of useless replies; here's my effort:
char data[8]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

int main ( void )
{
char a;
short b;
long c;
char* bpData;

// Set up the pointer to point to an odd address
bpData = &data[1];

// read a byte from an even address
a= *(bpData + 1);

Same as:

a = bpData[1];

and correct.
// Read a word from an odd address. This causes problems. Instead of
// getting 0x0102 I get 0x001. What does ANSI C say about this?
b= *(short*)(bpData) ;

This causes undefined behaviour because bpData might not be
correctly aligned for short. For example, on your system, shorts
might only be readable from even-numbered addresses.

Even if the alignment was correct, it could be that the two bytes
at that address do not form a valid bit-pattern for a short.

This isn't possible on normal 8-bit-byte 2s-complement systems.
But you may find yourself porting to a strange system one day,
and IMHO there is really no good reason to write code that uses
this assumption, when you can write correct code instead.

Even on a 'normal' system, this code will be relying on endianness
to get the value you want. For example a big-endian system would
give 0x0102 and a small-endian would give 0x0201.

The correct way to write the code is to remember that C works
on values, not representations:

b = bpData[0] * 256U + bpData[1];

The 'U' is important as it forces the arithmetic to be unsigned.

In case you are worried about efficiency, try inspecting the
assembly output generated and you should find that that code
reduces to a very simple instruction.

If not, then IMHO it is still better to have slightly-slower but
robust code, than your original code.

In fact it's most likely that you want bpData itself to be a
pointer to unsigned char, and the char array to be unsigned. If
you aren't attaching any significance to the sign bit, or if you
are storing values greater than 127, or if you are planning to
use bitwise operations on the chars, then you should make the
chars unsigned. (Note that 0x80 is NOT a valid value for a signed
char).
// just to check the value of the pointer, if the value of it is to
be stored in a variable
c= (long)bpData;

This is also a non-portable operation, use it with care. Using
an unsigned long instead of a signed one tends to be more
reliable.

return 0x0 ;

"return 0" will do just as well :)
 
K

Kenny McCormack

Mark McIntyre said:
Note however that you did get an answer to your question, and not one
which insulted you. Any percieved insult was entirely in your mind.

Oh, the irony. How absolutely vapid.

You do realize that that bit of rhetoric ("it is all in your mind") has
been used repeatedly down through the ages to justify just about every
attrocity, do you not?
 
O

Old Wolf

Christian said:
I did not explicitly write what alignment the processor uses, as this
is implicitly given in the example.

Actually it isn't; going on the original message alone, your
program could have all sorts of possible alignment requirements.
And again the alignment (odd or even) is not that relevant.
The question was in relation to pointer casting behaviour when
accessing non-aligned memory locations.

You did not mention this in the original message. You only
mentioned a pointer cast when accessing an odd-addressed
byte of a global char array.
Shall a compiler automatically do the trick for you to be ANSI
compliant or not. And excuse me for not knowing the standard by heart.

ISO 9899:1999 6.3.2.3#7:

A pointer to an object or incomplete type may be converted
to a pointer to a different object or incomplete type. If the
resulting pointer is not correctly aligned for the pointed-to
type, the behavior is undefined.

In this quote, the first pointer is bpData and the "different object
type"
is short.
The reason why I posted my question was because I was faced with the
claim that the compiler (in question) is not ANSI C compliant.

Now you know that the compiler does not violate the Standard
in this respect.

First of all I always retrieve 16 bit values( or larger) on systems like this
one by getting a single byte at a time (the code has to be platform
independant).

How is one supposed to know this from reading your original
message?

When you post bad code on a help forum, you have to expect to
get responses saying what the correct code is and why. If you
aren't interested in the correct code, simply ignore these responses,
rather than insulting the people who have taken time out of their
day in an effort to help.
And it not good practise to initialise variables within the declaration.

Most programmers would disagree with this.
Keep in mind that quite a few embedded systems are put into a
ROM chip, thereby creating the need for a patch system. To initialize
variables in the declaration will make the compiler put in code before
you can do a call to the patch system.

That's a peculiarity of your system, and off-topic for this NG.

By which I mean, it's all well and good if you want to do that,
but you have to expect that people on here will write the best
code.
I apologize for this angry reply, but I just got p***** off. You should
repect others more and answer any post in a professional way.

You should show respect by not top-posting, and not
abusing people who are trying to help you. Also you should not
abuse people for not mysteriously knowing things that you did
not write in your original post (eg. the fact that it was an
unaligned access). You should realise that it is in fact possible
that there are people in the world who are equal or better
programmers than you, and if they are to be found anywhere,
then this NG is a more likely place than most.
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

Christian said:
** SIGH ***

Your answer start out professionally but end as "I know all and you
know nothing"! Please do not post any replies if you do not have
respect for people.

I had assumed that people would disregard the EEPROM variable as the
question is not related to this. I did not explicitly write what
alignment the processor uses, as this is implicitly given in the
example. And again the alignment (odd or even) is not that relevant.
The question was in relation to pointer casting behaviour when
accessing non-aligned memory locations. Shall a compiler automatically
do the trick for you to be ANSI compliant or not. And excuse me for not
knowing the standard by heart.
As several people have told you by now. NO.
It is undefined behavior. ANSI C does not guarantee that that
cast will "work".
Some even provided a solution that doesn't invoke undefined behavior.


Please disregard the following sentences and only pay attention
to the above "It is undefined behavior" if this stirs up
your feelings:
Jack Klein told you this that it was undefined, and provided
several other helpful hints, and references to the relevarts
part of C according to your question. What did you fail to
understand about it ?
 
J

jjf

Christian said:
** SIGH ***

Your answer start out professionally but end as "I know all and you
know nothing"! Please do not post any replies if you do not have
respect for people.

I had assumed that people would disregard the EEPROM variable as the
question is not related to this. I did not explicitly write what
alignment the processor uses, as this is implicitly given in the
example. And again the alignment (odd or even) is not that relevant.
The question was in relation to pointer casting behaviour when
accessing non-aligned memory locations. Shall a compiler automatically
do the trick for you to be ANSI compliant or not. And excuse me for not
knowing the standard by heart.

The reason why I posted my question was because I was faced with the
claim that the compiler (in question) is not ANSI C compliant. First of
all I always retrieve 16 bit values( or larger) on systems like this
one by getting a single byte at a time (the code has to be platform
independant). But again, that was not the question. The question is the
casting and not whether this a the correct way to code.

For someone who claims to be an expert and who talks down to others, I
would expect a bit more insigth than this. And it not good practise to
initialise variables within the declaration. Keep in mind that quite a
few embedded systems are put into a ROM chip, thereby creating the need
for a patch system. To initialize variables in the declaration will
make the compiler put in code before you can do a call to the patch
system.

I apologize for this angry reply, but I just got p***** off. You should
repect others more and answer any post in a professional way.

Did you consider reading the answer, or did you just decide to ** SIGH
** about it?

Jack's article gives complete and thorough answers to your questions.
As he (and several others) pointed out, the construct you are using is
invalid C and results in undefined behaviour. A conforming Standard C
compiler can do anything it chooses to when it sees this construct.
/Christian




Jack Klein skrev:
Hi,

What does ANSI C say about casting an 8 bit pointer to a 16 bit one,

The C standard says nothing at all about "8 bit pointers" and "16 bit
pointers". It talks about pointers to types, and those types can have
different sizes on different implementations. But we'll assume for
the moment that you know that characters have 8 bits and shorts 16
bits on your platform.
when the byte pointer is pointing to an odd address? I have detected a
problem in the Samsung CalmShine 16 compiler. This compiler I use for
the Samsung 16 bit Smartcard chips and I want to know if it is
compliant with the ANSI standard or if it violates it.

The C standard says that the behavior is undefined.
Have a look at this super simple example, where the value of b is
incorrect:

#include <stdio.h>

// Define an array in the EEPROM memory at address 0x081000
char data[8]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} _at_
0x81000, eeprom;

Actually the minute you use the non-standard extension "_at_ 0x81000,
eprom", you have left the realm of the C standard behind. This means
nothing at all in standard C.

But assuming this results in a valid pointer to char...
int main ( void )
{
char a;
short b;
long c;
char* bpData;

// Set up the pointer to point to an odd address
bpData = &data[1];

If the non-standard definition does indeed create an array of chars
that your program has the right to access, this is a valid assignment
and places the address value 0x81000 in bpData.

But notice that you could have replaced the two lines with a simple
initialization in the definition of the pointer:

char *bpData = data + 1;
// read a byte from an even address
a= *(bpData + 1);

This is perfectly legal code, and assigned the contents of the char at
0x81002 to 'a'.
// Read a word from an odd address. This causes problems. Instead of
// getting 0x0102 I get 0x001. What does ANSI C say about this?
b= *(short*)(bpData) ;

The C standard says that if you use a pointer to something other than
a character type to access something, and the object does not have the
type of the pointer, the behavior is undefined.

C also says that when you convert pointer types, as your conversion
using a cast above, the result is undefined if the pointer is not
properly aligned for the new type.

I assume this is either a 16 or 32 bit processor, DSP, or
microcontroller. Some of these do have alignment requirements, and
accessing a 16-bit value on an odd address will violate these. The
results include a value that you consider "wrong", to generating a
hardware exception. An ARM, for example, will generate an address
abort.

Have you read the documentation on the processor, DSP, or
microcontroller that you are using? What are its address alignment
requirements?
// just to check the value of the pointer, if the value of it is to
be stored in a variable
c= (long)bpData;

return 0x0 ;
}

Someone who programs embedded systems in C, using architectures
dissimilar to typical desk top processors, needs to know a fair bit
more the C standard, especially if you try to do things like pointer
punning.
 

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,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top