[C/C++11]_[初级]_[简单介绍C++11对地址对齐的特性]

场景

1.在使用一些相关原子操作的函数或指令时, 一般都需要对操作的变量地址进行对齐, 4,8,16…字节对齐.

2.在没有引入C++11的alignas指示符之前, 一般都是使用

__declspec(align(4)) int i; // Windows  
alignas(4) int j; // C++

或定义一些存储空间进行计算转换, 参考数据地址对齐. 不同的是前者是编译时刻计算出地址,后者是运行时刻计算出内存对齐地址; 麻烦的是VS2010 并不是完整支持C++11对齐特性.

说明

1.C++11 引入了很多地址对齐相关的操作符, 函数, 模板。

alignas 说明符

1.同Windows的 __declspec(align(4)), VS2010不支持alignas 和 align(int)语法. 作用就是在编译时期分配对齐地址.


alignas( expression ) // alignas(4)   
alignas( type-id ) // alignas(int) 

alignof 操作符,alignment_of 类模板

1.他们是计算某个类型的对齐需要的字节数, 目前发现他们的值是一样的. 唯一不同的是前者是编译时计算,可用于模板,后者是运行时计算。


alignof( type-id )    

#include <type_traits>
template< class T >
struct alignment_of;

std::align 函数

1.和数据地址对齐里介绍的APR_ALIGN对齐一样, 用于运行时计算内存对齐存储地址. 可惜 VS2010 没有 std::align函数.

#include <memory>
void* align( std::size_t alignment,
             std::size_t size,
             void*& ptr,
             std::size_t& space );

std::aligned_storage 类模板

  1. 用于创建对齐静态数组, 即创建的数组里元素都是指定字节对齐的.
#include <type_traits>
template< std::size_t Len, std::size_t Align = /*default-alignment*/ >
struct aligned_storage;

例子

1.这里只是部分例子, 详细的说明符, 模板, 函数使用参考对应的链接.


#include <regex>
#include <assert.h>
#include <iostream>
#include <utility>
#include <stdint.h>
#include <iterator>
#include <set>
#include <typeinfO>
#include <iomanip>
#include <type_traits>

template<class _Ty>
  struct _Get_align
  { // struct used to determine alignemt of _Ty
  _Ty _Elt0;
  char _Elt1;
  _Ty _Elt2;
  };

#define _ALIGN_OF(ty) (sizeof(_Get_align<ty>) - 2 *sizeof(ty))

// Apache  
/* APR_ALIGN() is only to be used to align on a power of 2 boundary */  
#define APR_ALIGN(size1, boundary) (((size1) + ((boundary) - 1)) & ~((boundary) - 1))  

void TestAlign()
{
  int size1 = std::alignment_of<int64_t>().value;
  int size2 = _ALIGN_OF(int64_t);

  //1. 32字节对齐. 数值地址.要对齐地址,一般会创建多出的空间来对齐.  
    //1. 需要创建16字节空间,如果需要32字节对齐.  
    uint8_t* value = (uint8_t*)malloc(16+32);  
    std::cout <<"1 " << (int64_t)(int64_t*)(value) << std::endl;  
    int64_t* value_offset = (int64_t*)APR_ALIGN((int64_t)(int64_t*)value,32);  
    std::cout <<"2 " << (int64_t)(int64_t*)(value_offset) << std::endl;

  __declspec(align(32)) char buf[16] = {0}; // 如果去掉 align, assert基本上都会崩溃.
  assert(((int64_t)(void*)buf % 32) == 0);
  std::cout << (void*)buf << std::endl;

}

输出:

1 6981544
2 6981568
0039F740

参考

aligned_storage
align Windows
alignment_of
align
aligned_union
Alignment
alignas
parameter_pack
数据地址对齐
原子操作1

猜你喜欢

转载自blog.csdn.net/infoworld/article/details/80019825