0

I have an array uint8_t data[256]. But each element is single byte. My data bus is 32 bit long. So, If I want to access 32 bits, I do:

DATA = data[i] + (data[i + 1] << 8) + (data[i + 2] << 16) + (data[i + 3] << 24);

But this translates into 4 separate read requests in the memory of one byte each.

How can I access all the 4 bytes in the form of single transaction?

2
  • 1
    If data is of type int [256], not only one byte is read for each summand. Commented Oct 12, 2014 at 21:29
  • 1
    You would have to be using a very non-standard compiler to have int data[256]; be composed of single-bytes. The 'bytes' would have to be at least 16 bits each (CHAR_BIT == 16). There is some confusion in the assumptions you're making, I think. If, as one of your comments suggests, you mean uint8_t data[256];, then one question is 'are you going to index at values of i that are not multiples of 4'? and another question is 'what happens if you try to access an 'improperly aligned' memory address as a 4-byte unit?' You need to know the answers to both before risking short-cuts. Commented Oct 12, 2014 at 23:03

4 Answers 4

2

If you know the endian-ness of your data (or if you don't care), and your data is aligned (or have a byte-addressing process and you don't care about efficiency) you can cast data to a uint32_t * and access it in 4-byte chucks, like so:

DATA = ((uint32_t *)data)[i/4];

This of course assumes i is a multiple of 4.

Sign up to request clarification or add additional context in comments.

1 Comment

You should be more precise: If you know the target architecture to be little-endian.
1

Just cast data to uint32_t.

uint8_t data[256] = {1,2,3,4,5,6,7,8} ;

int main(int argc, char **argv)
{
  int index = 1 ;
  uint32_t d = *(uint32_t *)(data + index) ;
  printf ("%08x\n", d) ;
}

Output on a little endian architecture will be

05040302

Output on a big endian architecture will be

02030405

However depending on the achitecture of the processor your progam is running on, you might run into memory alignment problems (performance hit if you address an unaligned memory, or even a crash if your processor doesn't support unaligned memory addressing).

6 Comments

I tried this and this almost worked: The data that I have is 01,02,03,04,05,06,07,08... When I access the first location as *(long *)(data+0), I get 0x01030201 instead of 0x04030201. And when I access *(long *) (data+1), I get 0x05040302. This means data[4]=4, But the value returned is incorrect, do you have any idea, why this is the case?
The code works fine here. Ask a new question on stackoverflow with this specific issue.
Will the output depend on the chip architecture? I was under the impression that the output will be architecture-independent, just like bit-shifting, etc. This would explain why @Rgarg got 0x05040302 and not the little-endian representation even though he/she is likely on a chip using little-endian representation under the hood.
uint32_t d = *(uint32_t *)(data + index) ; with index = 1 is an unaligned access, with potential undefined behavior.
@chqrlie that was already mentioned in the last sentence of the answer.
|
0

Maybe you should store data as an array of 32-bit:

uint32_t data[64];
DATA = data[i];
DATA = data[i+1];
...

2 Comments

I cannot modify the array. Its a constraint. But if we look at it, from the memory perspective, isn't it the same thing? uint32_t data[64] and uint8_t data[256]?
@Rgarg: What is the type of your array? In the question, you say int data[256]; but here in your comment you seem to be saying uint8_t data[256]; — these are very different! It makes a wreck out of your question, in fact.
-1

As @dwayne-towell mentioned - you need to care of endianness of you data. In one transaction it might be realized like an example below:

#include <stdio.h>
#include <stdint.h>

int
main()
{
        uint8_t data[256];
        uint32_t i, *p;

        // Add some 32bit numbers
        p = (uint32_t *)data;
        for (i = 0; i < sizeof(data)/sizeof(uint32_t); ++i) {
                *(p++) = i;
        }

        // Print some 32bit numbers
        p = (uint32_t *)data;
        for (i = 0; i < sizeof(data)/sizeof(uint32_t); ++i) {
                printf("value=%u\n", *(p++));
        }

        return (0);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.