比较的宏以及typeof()类型判断宏`
|
- 使用
typeof()类转换宏处理 typeof(a) _a = (a)定义一个a类型的变量,值等于a(void) (&_a == &_b)判断二者类型是否相同,不同的话会出现警告typeof(int *) a,b;//等价于:int *a,*b;
零长数组(变长数组)
- 满足需要变长度的结构体,因此有时也习惯性地称为变长数组。
- 在一个结构体的最后, 申明一个长度为0的数组, 就可以使得这个结构体是可变长的
struct line {
int length;
char contents[0];
};
struct line *thisline = malloc(sizeof(struct line) + this_length);
thisline->length = this_length; - 上述结构体本身的大小只有一个length的大小,不包括content
- 创建的时候人为分配空间给contents即可
switch case的条件指定范围
case low ... high: |
- 还可以用整形数来表示范围,但是这里需要注意在“…”两边有空格
struct的指定成员初始化
|
- 上文中的指定名称初始化是
// 定义点操作的结构体并初始化函数指针
struct PointOperations pointOps = {
.calculateDistance = calculateDistance,
.printCoordinates = printCoordinates
}; - 这里可以手动指定需要初始化的结构体成员的名字
可变参数宏
dynamic_pr_debug 是 Linux 内核中用于动态调试打印的宏,而 fmt 和
__VA_ARGS__则是格式化字符串和可变参数列表。fmt:格式化字符串,类似于 printf 中的格式化字符串,包含要打印的文本和格式说明符。
__VA_ARGS__:表示可变参数的宏,用于将额外的参数传递给 fmt 中的格式说明符。##__VA_ARGS__是一个预处理器技巧,用于处理当可变参数列表为空时的情况,确保宏在没有额外参数时也能正确展开
函数属性 __attribute__
__attribute__ ((attribute-list))attribute-list的定义有很多,如noreturn、format以及const等。此外,还可以定义一些和处理器体系结构相关的函数属性void __attribute__((noreturn)) die(void);
其他属性
变量属性和类属性
变量属性可以对变量或结构体成员进行属性设置。类型属性常见的属性有
alignment、packed和sections等。alignment属性规定变量或者结构体成员的最小对齐格式,以字节为单位struct qib_user_info {
__u32 spu_userversion;
__u64 spu_base_info;
} __aligned(8);上述例子中结构体存储会以八字节对齐
struct test{
char a;
int x[2] __attribute__ ((packed));
};x成员使用了packed属性,它会存储在变量a后面,所以这个结构体一共占用9字节
内建函数
内建函数以“_builtin_”作为函数名前缀。下面介绍Linux内核常用的一些内建函数
__builtin_constant_p(x):判断x是否在编译时就可以被确定为常量。如果x为常量,该函数返回1,否则返回0__builtin_expect(exp, c):这里的意思是exp==c的概率很大,用来引导GCC编译器进行条件分支预测__builtin_prefetch(const void *addr, int rw, int locality):主动进行数据预取,在使用地址addr的值之前就把其值加载到cache中,减少读取的延迟,从而提高性能。该函数可以接受3个参数:
- 第一个参数addr表示要预取数据的地址;
- 第二个参数rw表示读写属性,1表示可写,0表示只读;
- 第三个参数locality表示数据在cache中的时间局部性,其中0表示读取完addr的之后不用保留在cache中,而1~3表示时间局部性逐渐增强
asmlinkage
- 在标准C语言中,函数的形参在实际传入参数时会涉及参数存放问题
- 对于x86架构,函数参数和局部变量被一起分配到函数的局部堆栈里
<arch/x86/include/asm/linkage.h>
- 告诉编译器一个声明了
asmlinkage的函数不需要通过任何寄存器来传递参数,只通过堆栈来传递 - 用法
asmlinkage void my_assembly_function(int arg1, int arg2)
{
// 汇编函数的实现
// ...
} - asmlinkage 用于标识 my_assembly_function 是一个汇编语言编写的函数,并且该函数使用堆栈而不是寄存器来传递参数
- 对于ARM来说,函数参数的传递有一套ATPCS标准,即通过寄存器来传递。ARM中的R0~R4寄存器存放传入参数,当参数超过5个时,多余的参数被存放在局部堆栈中
- ARM平台没有定义asmlinkage
switch case和枚举类型配合使用
|
- 此前包含一个枚举类型的定义包括
DEBUG等 - 这个可以将枚举类型的数字逆向映射为字符串(通过
#name转换为字符串)
std::enable_shared_from_this
- 安全的获取一个对象的this指针
- 防止重复析构等情况
- 使用
shared_from_this()函数返回当前函数的共享指针 - 使用例
class Widget : public std::enable_shared_from_this<Widget>{
public:
Widget(){
std::cout << "Widget constructor run" << std::endl;
}
~Widget(){
std::cout << "Widget destructor run" << std::endl;
}
std::shared_ptr<Widget> GetSharedObject(){
return shared_from_this();
}
};
int main()
{
std::shared_ptr<Widget> p(new Widget());
std::shared_ptr<Widget> q = p->GetSharedObject();
std::cout << p.use_count() << std::endl;
std::cout << q.use_count() << std::endl;
return 0;
}
thread_local关键字
thread_local是 C++11 标准引入的关键字,用于声明线程局部存储(Thread-local storage,TLS)变量。线程局部存储意味着每个线程都有自己独立的变量副本,这样可以避免线程间的竞争条件- 使得每个线程都有自己独立的某个这个变量的副本而不是与其他线程共享
thread_local int threadSpecificValue = 0;
void threadFunction() {
// 每个线程都有独立的 threadSpecificValue
threadSpecificValue += 1;
std::cout << "Thread Specific Value: " << threadSpecificValue << std::endl;
}
int main() {
// 创建两个线程,并在每个线程中调用 threadFunction
std::thread t1(threadFunction);
std::thread t2(threadFunction);
// 等待线程执行完成
t1.join();
t2.join();
return 0;
}