C++:静态断言&内存对齐

发布于:2024-06-30 ⋅ 阅读:(137) ⋅ 点赞:(0)

静态断言

  • C中的断言assert
    (1)直接参考:https://www.cnblogs.com/lvchaoshun/p/7816288.html
    (2)C的assert是运行时检测发现错误,而不是编译时
    (3)C在编译时错误用#error来输出
  • C++静态断言
    (1)C++引入static_assert(表达式, “提示字符串”)来实现编译时的静态断言
    (2)实例演示
#include <iostream>
#include <type_traits>

// 编译期常量表达式
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : (n * factorial(n - 1));
}

int main() {
    // 编译时断言:检查某些条件是否成立
    static_assert(sizeof(int) == 4, "int 类型的大小不是 4 字节");
    static_assert(factorial(5) == 120, "Factorial 计算错误");
    
    std::cout << "所有静态断言均通过。" << std::endl;

    return 0;
}

#include <iostream>
#include <cassert>

int factorial(int n) {
    assert(n >= 0); // 断言n是非负数
    if (n == 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

int main() {
    int num1 = 5;
    int num2 = -3;

    // 正常情况
    std::cout << "Factorial of " << num1 << " is " << factorial(num1) << std::endl;

    // 异常情况(将触发断言)
    std::cout << "Factorial of " << num2 << " is " << factorial(num2) << std::endl;

    return 0;
}

  • 静态断言主要用途
    (1)static_assert主要用于检查模板参数是否符合期望
    (2)C++20中引入了concept来进一步更好的实现模板参数的编译时类型匹配检查

内存对齐

  • C语言中内存对齐关键点
    (1)#pragma 和 attribute((packed)) attribute((aligned(n)))
#include <stdio.h>

// 使用 #pragma pack 控制对齐
#pragma pack(push, 1) // 设置为1字节对齐

typedef struct {
    char c;
    int i;
    double d;
} PackedStruct;

#pragma pack(pop) // 恢复默认对齐

// 使用 __attribute__((packed)) 控制对齐
typedef struct {
    char c;
    int i;
    double d;
} __attribute__((packed)) PackedStructAttribute;

// 使用 __attribute__((aligned(n))) 控制对齐
typedef struct {
    char c;
    int i;
    double d;
} AlignedStruct __attribute__((aligned(16)));

int main() {
    PackedStruct ps;
    PackedStructAttribute psa;
    AlignedStruct as;

    printf("Size of PackedStruct: %zu bytes\n", sizeof(PackedStruct));
    printf("Size of PackedStructAttribute: %zu bytes\n", sizeof(PackedStructAttribute));
    printf("Size of AlignedStruct: %zu bytes\n", sizeof(AlignedStruct));

    printf("Address of ps.c: %p\n", (void*)&ps.c);
    printf("Address of ps.i: %p\n", (void*)&ps.i);
    printf("Address of ps.d: %p\n", (void*)&ps.d);

    printf("Address of psa.c: %p\n", (void*)&psa.c);
    printf("Address of psa.i: %p\n", (void*)&psa.i);
    printf("Address of psa.d: %p\n", (void*)&psa.d);

    printf("Address of as.c: %p\n", (void*)&as.c);
    printf("Address of as.i: %p\n", (void*)&as.i);
    printf("Address of as.d: %p\n", (void*)&as.d);

    return 0;
}

在这里插入图片描述

  • C++中内存对齐新增关键字
    (1)alignof (C++11 起) 查询对齐要求
    (2)alignas (C++11 起)设置对齐,效果:和__attribute__((aligned(n)))效果一样,往大了设置有用
#include <iostream>
#include <cstddef> // for std::size_t

// 使用 alignas 设置对齐
struct alignas(16) AlignedStruct {
    char c;
    int i;
    double d;
};

// 未对齐的结构体
struct UnalignedStruct {
    char c;
    int i;
    double d;
};

int main() {
    // 使用 alignof 查询对齐要求
    std::cout << "Alignment of char: " << alignof(char) << std::endl;
    std::cout << "Alignment of int: " << alignof(int) << std::endl;
    std::cout << "Alignment of double: " << alignof(double) << std::endl;

    std::cout << "Alignment of AlignedStruct: " << alignof(AlignedStruct) << std::endl;
    std::cout << "Alignment of UnalignedStruct: " << alignof(UnalignedStruct) << std::endl;

    // 打印结构体大小
    std::cout << "Size of AlignedStruct: " << sizeof(AlignedStruct) << std::endl;
    std::cout << "Size of UnalignedStruct: " << sizeof(UnalignedStruct) << std::endl;

    // 分配对齐的内存
    void* ptr = aligned_alloc(alignof(AlignedStruct), sizeof(AlignedStruct));
    if (ptr) {
        std::cout << "Memory allocated at address: " << ptr << std::endl;
        free(ptr); // 记得释放内存
    } else {
        std::cerr << "Memory allocation failed!" << std::endl;
    }

    return 0;
}

在这里插入图片描述

  • 什么情况下需要人为改变/指定对齐方式
    (1)往大去对齐。有时候会有一些硬件特殊要求,譬如MMU,cache等。用__attribute__((aligned(n)))实测ok,用#pragma实测不ok
    (2)往下去对齐。有时候需要节省内存而浪费效率,所以希望忽略内存对齐,紧密排放。用#pramgma实测ok,用__attribute__((aligned(n)))实测不ok

总结

了解static_assert的使用方法
了解alignof 、alignas,可以实现内存对齐

学习记录,侵权联系删除。
来源:朱老师物联网大课堂


网站公告

今日签到

点亮在社区的每一天
去签到