By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,836 Members | 2,011 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,836 IT Pros & Developers. It's quick & easy.

Accessing members of array as a different type

P: n/a
Hi,

I'm having trouble geting my head around this, although I know it's a pretty
basic question.

I have an application whereby an area of RAM is mapped to an array:

unsigned char NV[128];

Two consequtive elements are used to hold an unsigned int (2 bytes on this
platform). How do I access it as an unsigned int?

e.g.
unsigned int test;
....
test = *(unsigned int *)(&(NV[15]);

In this case, I'm trying to retrieve the unsigned int value represented by
elements 15 & 16 of the array. It does not seem to be working.

Could someone please explain what I'm doing wrong.

Many thanks,

James
Nov 14 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
James A <me@privacy.net> wrote:
I'm having trouble geting my head around this, although I know it's a pretty
basic question. I have an application whereby an area of RAM is mapped to an array: unsigned char NV[128]; Two consequtive elements are used to hold an unsigned int (2 bytes on this
platform). How do I access it as an unsigned int? e.g.
unsigned int test;
...
test = *(unsigned int *)(&(NV[15]); In this case, I'm trying to retrieve the unsigned int value represented by
elements 15 & 16 of the array. It does not seem to be working.


It would be helpful to tell what you mean by "not seem to be working".
That construct could, for example, crash your program with a SIGBUS
error because of an unaligned access. Or it could work but deliver
an unexpected result. But what you expect is something that no-one
can figure out from what you write, so it could be that the numbers
you're expecting in memory are stored in big-endian order while you
try to do all of that on a little endian machine etc. Or it could
be because what you try to read belongs actually to two different
2-byte numbers (if, as you write, all the 128 bytes are occupied
by 64 2-byte numbers).
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #2

P: n/a

"James A" <me@privacy.net> wrote in message
news:q6**************@newsfe2-gui.ntli.net...
Hi,

I'm having trouble geting my head around this, although I know it's a pretty basic question.

I have an application whereby an area of RAM is mapped to an array:

unsigned char NV[128];

Two consequtive elements are used to hold an unsigned int (2 bytes on this
platform). How do I access it as an unsigned int?

e.g.
unsigned int test;
...
test = *(unsigned int *)(&(NV[15]);

In this case, I'm trying to retrieve the unsigned int value represented by
elements 15 & 16 of the array. It does not seem to be working.

Could someone please explain what I'm doing wrong.


You don't give enough information. E.g.
How was the data originally stored?

#include <stdio.h>

int main()
{
unsigned char NV[128] = {0};
unsigned int test = 0;

NV[15] = NV[16] = 0xAA;
test = *(unsigned int *)(NV + 15);

printf("%u\n", test); /* prints 43690 for implementations with
*/
/* two-byte unsigned int and for 'little-endian'
*/
/* (e.g. most PC's) platforms with a larger
*/
/* unsigned int
*/

return 0;
}

-Mike

Nov 14 '05 #3

P: n/a
On Thu, 16 Sep 2004 18:40:22 GMT
"James A" <me@privacy.net> wrote:
I'm having trouble geting my head around this, although I know it's a
pretty basic question.

I have an application whereby an area of RAM is mapped to an array:

unsigned char NV[128];

Two consequtive elements are used to hold an unsigned int (2 bytes on
this platform). How do I access it as an unsigned int?

e.g.
unsigned int test;
...
test = *(unsigned int *)(&(NV[15]);
You seem to have mismatched brackets. I assume this was a typo and not
the problem in your actual code.
In this case, I'm trying to retrieve the unsigned int value
represented by elements 15 & 16 of the array. It does not seem to be
working.

Could someone please explain what I'm doing wrong.


What you are doing wrong is invoking undefined behaviour when you don't
need to. One reason why this might fail on real implementations is due
to alignment restrictions, other reasons for failure include having more
than 5 minutes in a day. Depending on what you are trying to achieve
something like
test = ((unsigned int)NV[15] << CHAR_BIT) || NV[16]
or possibly
test = ((unsigned int)NV[16] << CHAR_BIT) || NV[15]

Of course, if by "area of RAM is mapped to an array" you mean some RAM
written to by some other (e.g. if it is DPRAM) then you would also need
to declare NV as volatile.
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #4

P: n/a
"Mike Wahler" <mk******@mkwahler.net> wrote in message
news:P_*****************@newsread1.news.pas.earthl ink.net...

"James A" <me@privacy.net> wrote in message
news:q6**************@newsfe2-gui.ntli.net...
Hi,

I'm having trouble geting my head around this, although I know it's a

pretty
basic question.

I have an application whereby an area of RAM is mapped to an array:

unsigned char NV[128];

Two consequtive elements are used to hold an unsigned int (2 bytes on this platform). How do I access it as an unsigned int?

e.g.
unsigned int test;
...
test = *(unsigned int *)(&(NV[15]);

In this case, I'm trying to retrieve the unsigned int value represented by elements 15 & 16 of the array. It does not seem to be working.

Could someone please explain what I'm doing wrong.


You don't give enough information. E.g.
How was the data originally stored?

#include <stdio.h>

int main()
{
unsigned char NV[128] = {0};
unsigned int test = 0;

NV[15] = NV[16] = 0xAA;
test = *(unsigned int *)(NV + 15);

printf("%u\n", test); /* prints 43690 for implementations with
*/
/* two-byte unsigned int and for 'little-endian'
*/
/* (e.g. most PC's) platforms with a larger
*/
/* unsigned int
*/

return 0;
}

-Mike


Many thanks Mike, Flash and Jens for your replies and advice.

Sorry for the lack of info. Here is hopefully what is needed:

By not working, I mean the unsigned int value stored is not the same value
returned later on.

Here is the code that should be storing the value:

unsigned int a, b;
...
*(unsigned int *)(&(NV[15])) = a;

The code that retreives the value later on in the code is this:

b = *(unsigned int *)(&(NV[15]));

[Apologies for the bracket error in the original post]

But in my testing, b does not equal a.

Debugging is somewhat tricky (the platform is a small embedded processor
[PIC12]) but the symptoms suggest that the most significant byte of the
unsigned int is being retrieved with the incorrect contents. The compiler
documentation says it uses little-endian format for its 16-bit unsigned
ints.

This problem might be down to me overwriting the area of the array concerned
elsewhere in the code. Could someone please say if the code above should
work ok. Then I can either eliminate it from my search, or go about fixing
it.

Thanks for all your help and patience!

James
Nov 14 '05 #5

P: n/a
James A <me@privacy.net> wrote:
By not working, I mean the unsigned int value stored is not the same value
returned later on. Here is the code that should be storing the value: unsigned int a, b;
...
*(unsigned int *)(&(NV[15])) = a; The code that retreives the value later on in the code is this: b = *(unsigned int *)(&(NV[15]));
That looks pretty good and should work (unless there are some align-
ment issues on your machine, but if this does not crashes the program
it should not be a problem). Actually, you could simplify that to

b = * ( unsigned int * ) ( NV + 15 );

etc., which I at least would find easier to read.
But in my testing, b does not equal a. Debugging is somewhat tricky (the platform is a small embedded processor
[PIC12]) but the symptoms suggest that the most significant byte of the
unsigned int is being retrieved with the incorrect contents.
Are you sure you're not writing to some hardware registers instead
of some simple memory? I just ask because you were writing about a
"memory range" and now about an "embedded processor" (which may use
memory mapped I/O) - so when there's some hardware register mapped
into that memory range and you accidentally hit one all bets are off,
of course...
The compiler documentation says it uses little-endian format for
its 16-bit unsigned ints.
If you compare what you have written yourself with what you read endian-
ness shouldn't be an issue here - it could be a problem if that would be
a buffer with some binary data you have received from a different machine.
This problem might be down to me overwriting the area of the array concerned
elsewhere in the code. Could someone please say if the code above should
work ok. Then I can either eliminate it from my search, or go about fixing
it.


I don't see why it shouldn't work. Checking if it does should be not too
difficult - write a short program that writes to a memory location this
way and read in what you have written immediately again. If this fails
something strange is going on (while I don't guess it will, one never
knows until one has tested it;-), otherwise it's a safe bet that some-
thing has overwritten the memory in between writing and reading.

If it does not work, you still can go the clean, portable road by
simply using memcpy(), i.e.

memcpy( NV + 15, &a, sizeof a );
...
memcpy( &b, NV + 15, sizeof b );

If this also fails you can be sure that either your memory is bad or
that it's not real memory at all.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #6

P: n/a
<Je***********@physik.fu-berlin.de> wrote in message
news:2q*************@uni-berlin.de...
James A <me@privacy.net> wrote:
By not working, I mean the unsigned int value stored is not the same value returned later on.

Here is the code that should be storing the value:

unsigned int a, b;
...
*(unsigned int *)(&(NV[15])) = a;

The code that retreives the value later on in the code is this:

b = *(unsigned int *)(&(NV[15]));


That looks pretty good and should work (unless there are some align-
ment issues on your machine, but if this does not crashes the program
it should not be a problem). Actually, you could simplify that to

b = * ( unsigned int * ) ( NV + 15 );

etc., which I at least would find easier to read.
But in my testing, b does not equal a.

Debugging is somewhat tricky (the platform is a small embedded processor
[PIC12]) but the symptoms suggest that the most significant byte of the
unsigned int is being retrieved with the incorrect contents.


Are you sure you're not writing to some hardware registers instead
of some simple memory? I just ask because you were writing about a
"memory range" and now about an "embedded processor" (which may use
memory mapped I/O) - so when there's some hardware register mapped
into that memory range and you accidentally hit one all bets are off,
of course...
The compiler documentation says it uses little-endian format for
its 16-bit unsigned ints.


If you compare what you have written yourself with what you read endian-
ness shouldn't be an issue here - it could be a problem if that would be
a buffer with some binary data you have received from a different machine.
This problem might be down to me overwriting the area of the array concerned elsewhere in the code. Could someone please say if the code above should
work ok. Then I can either eliminate it from my search, or go about fixing it.


I don't see why it shouldn't work. Checking if it does should be not too
difficult - write a short program that writes to a memory location this
way and read in what you have written immediately again. If this fails
something strange is going on (while I don't guess it will, one never
knows until one has tested it;-), otherwise it's a safe bet that some-
thing has overwritten the memory in between writing and reading.

If it does not work, you still can go the clean, portable road by
simply using memcpy(), i.e.

memcpy( NV + 15, &a, sizeof a );
...
memcpy( &b, NV + 15, sizeof b );

If this also fails you can be sure that either your memory is bad or
that it's not real memory at all.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de


Hi Jens,

Many thanks for your reply. I like your simplification of the code and will
switch to that - much more readable I agree! And thank you for confirming
that the code itself is not at fault - the problem must be somewhere else.

I didn't want to talk too much about the platform as I know this is a
generic C language group, so kept the details to a minimum. FWIW, the array
is declared using a qualifier that means it uses non-volatile memory in the
PIC - I use it to store various values that need to be retained across power
cycles. Unfortunately ROM space is incredibly tight so I had to switch from
discrete variables to a single, multi-purpose array in order to save a few
bytes in the compile size, and somewhere down the line this bug has crept
in.

Armed with your info and suggestions I should be able to track the problem
down soon.

Cheers,
James
Nov 14 '05 #7

P: n/a
On 17 Sep 2004 00:08:45 GMT
Je***********@physik.fu-berlin.de wrote:
James A <me@privacy.net> wrote:
By not working, I mean the unsigned int value stored is not the same
value returned later on.
Here is the code that should be storing the value:

unsigned int a, b;
...
*(unsigned int *)(&(NV[15])) = a;

The code that retreives the value later on in the code is this:

b = *(unsigned int *)(&(NV[15]));


That looks pretty good and should work (unless there are some align-
ment issues on your machine, but if this does not crashes the program
it should not be a problem). Actually, you could simplify that to


<snip>

Not true. The processor could just silently ignore the low bit of the
address or do something else even more screwy. Crashing is only the
nicest way it can fail.

<snip>
If it does not work, you still can go the clean, portable road by
simply using memcpy(), i.e.

memcpy( NV + 15, &a, sizeof a );
...
memcpy( &b, NV + 15, sizeof b );

If this also fails you can be sure that either your memory is bad or
that it's not real memory at all.


This is a very good suggestion.
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.