在8字節(jié)對(duì)齊的情況下指針的低三位都是0罕拂,在某些情況下我們需要維持跟指針對(duì)應(yīng)的額外信息,例如標(biāo)志位全陨,但是又不想為此創(chuàng)建一個(gè)結(jié)構(gòu)體爆班,那就可以利用指針的低三位來存儲(chǔ)額外信息。
比如說我們希望原子操作的類型是64位的數(shù)據(jù)辱姨,這樣可以利用CMPXCHG機(jī)器指令實(shí)現(xiàn)CAS操作柿菩,即我們希望定義std::atomic<T *>
的變量實(shí)現(xiàn)原子操作,而不希望定義std::atomic<S>
雨涛,S為某個(gè)結(jié)構(gòu)體枢舶。這時(shí)候就可以應(yīng)用上述技巧懦胞。
具體實(shí)現(xiàn)方式如下所示:
std::uintptr_t
是定義一個(gè)可以表示地址值(指針值即地址值)的無符號(hào)整型。將指針轉(zhuǎn)換成std::uintptr_t
然后進(jìn)行位運(yùn)算凉泄。以下代碼作為示例:
#include <iostream>
#include <stdint.h>
struct Data
{
// 定義一些數(shù)據(jù)成員
long int a;
long int b;
long int c;
};
// 定義三個(gè)標(biāo)志位躏尉,不用細(xì)究三個(gè)標(biāo)志位的具體含義,這個(gè)在這里不重要后众。
static constexpr std::uintptr_t HAS_DATA = 1;
static constexpr std::uintptr_t NEED_DATA = 2;
static constexpr std::uintptr_t CLOSED = 4;
static constexpr std::uintptr_t FLAGS_MASK = HAS_DATA | NEED_DATA | CLOSED;
static constexpr std::uintptr_t PTR_MASK = ~FLAGS_MASK;
int main()
{
Data * dp = new Data();
dp->a = 88;
dp->b = 99;
dp->c = 77;
std::cout << "指針值為 " << std::hex << reinterpret_cast<int64_t>(dp) << std::endl;
// 在指針上附加上標(biāo)志位
std::uintptr_t ptr_int = reinterpret_cast<std::uintptr_t>(dp) | HAS_DATA;
std::cout << "加過標(biāo)記位后 " << std::hex << ptr_int << std::endl;
// 取標(biāo)志位
std::uintptr_t flags = ptr_int & FLAGS_MASK;
std::cout << "標(biāo)記位 " << flags << std::endl;
// 需要用指針的時(shí)候胀糜,清零低三位,恢復(fù)指針值原來的值
dp = reinterpret_cast<Data*>(ptr_int & PTR_MASK);
std::cout << "使用恢復(fù)后的指針" << std::dec << dp->a << ", " << dp->b << ", " << dp->c << std::endl;
return 0;
}