Declare, manipulate and access unaligned memory in C++ [closed]

纵然是瞬间 提交于 2019-12-24 10:49:16

问题


I recently posted a question about unaligned memory access, but given the answer, I am a little lost. I often hear that "aligned memory access is far more efficient than unaligned access", but I am actually not sure what is unaligned memory. Consequently:

  • What is unaligned memory?
  • How you declare something unaligned in C++? (small example program)
  • How do you access and manipulate something unaligned in C++? (small example program)
  • Is there is a way to manipulate unaligned memory in with a defined behavior approach or all of that is platform dependent/undefined behavior in C++?

回答1:


Whether something is unaligned or not depends on the data type and its size As the answer from Gregg explains.

A well-written program usually does not have unaligned memory access, except when the compiler introduces it. (Yes, that happens during vectorization but let's skip that).

But you can write program in C++ to force unaligned memory access. The code below does just that.

#include <iostream>
using namespace std;
int main() {

  int a[3] {1, 2, 3};

  cout << *((long long *)(&a[0])) << endl;
  cout << *((long long *)(&a[1])) << endl;

  cout <<  (long long) (&a[0]) << endl;
  cout << (long long) (&a[1]) << endl;

  return 0;

}

The output of the code is this

8589934593
12884901890
70367819479584
70367819479588

What this program does? I declare an integer array of size 3. This array will be 4 byte aligned because int is a 4 byte data type (at least on my platform). So the address of a[0] is divisible by 4. Now address of both of a[0] and a[1] is divisible by 4 but only address of one of them is divisible by 8.

So if I cast the address of a[0] and a[1] to a pointer to long long (which is an 8 byte data type on my platform) and then deference these two pointers, one of them will be an unaligned memory access. This is not undefined behavior AFAIK, but it is going to be slower than aligned memory access.

As you see this code contains C style casts which is not a good practice. But I think for enforcing some strange behavior that is fine.

let me know if you have question about the output of the code. You should know about endianness and representation of integers to understand the first two lines. The third and fourth line are address of the first two elements of the integer array. That should be easier to understand.




回答2:


taking an example of a 32 bit computer reading a 4 byte word of data:

In the hardware, a 32 bit computer reads 4 bytes at a time but only on every 4th byte. This is because the memory bus is 4 bytes wide.

If your 4 byte data does not start on one of those 4 byte boundaries, the computer must read the memory twice, and then assemble the 4 bytes to a single register internally.

Based on the architecture chosen, the compiler knows this and places/pads data structures so that two byte data occur on two byte boundaries, 4 byte data starts on 4 byte boundaries, etc. This is specifically to avoid mis-aligned reads.

You can get misaligned reads if you read data in as bytes (like from a serial protocol) and then access them as 32 bit words. Avoid this in speed critical code. Usually it is taken care of for you and is not a problem.



来源:https://stackoverflow.com/questions/39922500/declare-manipulate-and-access-unaligned-memory-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!