ARRAY_SIZE宏作用及使用注意事项

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习

🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发

❄️作者主页:一个平凡而乐于分享的小比特的个人主页

✨收录专栏:c语言重要知识点总结,本专栏旨在总结C语言学习过程中的易错点,通过调试代码,分析原理,对重要知识点有更清晰的理解

欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

ARRAY_SIZE宏作用及使用注意事项

ARRAY_SIZE 宏是C/C++中用于在编译时获取数组元素个数的常用宏。我来详细讲解它的原理、作用和注意事项。

1. 基本定义

c 复制代码
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

2. 工作原理

示例说明

c 复制代码
int arr[10];
size_t size = ARRAY_SIZE(arr);  // 展开为: sizeof(arr) / sizeof(arr[0])
                               // = (10 * sizeof(int)) / sizeof(int)
                               // = 10

3. 主要作用

3.1 遍历数组更安全

c 复制代码
int arr[] = {1, 2, 3, 4, 5};  // 编译器自动计算为5个元素

// 传统方式需要手动计算
for (int i = 0; i < 5; i++) { ... }

// 使用ARRAY_SIZE更安全
for (size_t i = 0; i < ARRAY_SIZE(arr); i++) {
    // 自动适应数组大小变化
}

3.2 防止硬编码魔法数字

c 复制代码
// 不好的写法
process_array(arr, 10);

// 好的写法
process_array(arr, ARRAY_SIZE(arr));

4. 重要注意事项

4.1 不能用于指针

c 复制代码
// 错误用法示例
void bad_example(int *ptr) {
    size_t size = ARRAY_SIZE(ptr);  // 错误!ptr是指针,不是数组
}

void test() {
    int arr[10];
    int *ptr = arr;
    
    size_t s1 = ARRAY_SIZE(arr);  // 正确:10
    size_t s2 = ARRAY_SIZE(ptr);  // 错误:sizeof(ptr)是指针大小,不是数组大小
}

4.2 不能用于动态分配的数组

c 复制代码
int *dynamic_arr = malloc(10 * sizeof(int));
size_t size = ARRAY_SIZE(dynamic_arr);  // 错误!得到的是指针大小/元素大小

4.3 宏参数必须是数组类型

c 复制代码
// Linux内核中的安全版本(部分实现)
#define ARRAY_SIZE(arr) \
    (__builtin_types_compatible_p(typeof(arr[0])[], typeof(arr)) ? \
     sizeof(arr) / sizeof((arr)[0]) : -1)

4.4 C++中的替代方案

cpp 复制代码
// C++11以后可以使用模板
template<typename T, size_t N>
constexpr size_t array_size(T (&)[N]) { return N; }

// 或者使用std::array
#include <array>
std::array<int, 5> arr;
size_t size = arr.size();

5. 实际应用场景

5.1 初始化数组

c 复制代码
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
const size_t days_count = ARRAY_SIZE(days);  // 自动得到7

5.2 安全的内存操作

c 复制代码
int src[100];
int dest[ARRAY_SIZE(src)];  // 确保目标数组足够大
memcpy(dest, src, sizeof(src));

5.3 结构体数组处理

c 复制代码
struct Student {
    int id;
    char name[20];
};

struct Student students[50];
size_t student_count = ARRAY_SIZE(students);

6. 高级技巧

6.1 编译时断言

c 复制代码
// 确保数组大小符合预期
#define STATIC_ASSERT_ARRAY_SIZE(arr, expected) \
    static_assert(ARRAY_SIZE(arr) == expected, "Array size mismatch")

int my_array[10];
STATIC_ASSERT_ARRAY_SIZE(my_array, 10);  // 编译时检查

6.2 安全遍历

c 复制代码
#define FOREACH_ARRAY(item, arr) \
    for (size_t i = 0, _count = ARRAY_SIZE(arr); i < _count && (item = &arr[i], 1); i++)

int arr[] = {1, 2, 3, 4, 5};
FOREACH_ARRAY(int *item, arr) {
    printf("%d\n", *item);
}

7. 常见错误总结

  1. 误用于指针:最常见的错误

  2. 在函数参数中使用 :数组参数会退化为指针

    c 复制代码
    void func(int arr[]) {
        size_t size = ARRAY_SIZE(arr);  // 错误!arr是指针
    }
  3. 忘记包含必要的头文件sizeof需要知道类型大小

  4. 混合使用C和C++:C++有更好的替代方案

8. 最佳实践建议

  1. 在宏定义前后加括号

    c 复制代码
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  2. 使用size_t类型存储结果

    c 复制代码
    size_t count = ARRAY_SIZE(arr);  // 正确
    int count = ARRAY_SIZE(arr);     // 可能丢失精度
  3. 考虑使用更安全的变体

    c 复制代码
    // GNU扩展版本
    #define ARRAY_SIZE(arr) \
        (sizeof(arr) / sizeof((arr)[0]) + \
         sizeof(typeof(int[1 - 2 * !!__builtin_types_compatible_p(typeof(arr), typeof(&arr[0]))])) * 0)
  4. 明确文档说明:在团队代码中注明宏的限制

总结

ARRAY_SIZE是一个简单但强大的宏,正确使用时能显著提高代码的安全性和可维护性。关键是记住它的核心限制只能用于真正的数组,不能用于指针。在C++中,考虑使用类型安全的替代方案。

相关推荐
leaves falling2 小时前
c语言-编译和链接
c语言·开发语言
VekiSon2 小时前
ARM架构——UART 串口通信详解
c语言·arm开发·单片机·嵌入式硬件
LYS_06182 小时前
RM赛事C型板九轴IMU解算(3)(姿态融合算法)
c语言·算法·imu·姿态解算·四元数到欧拉角
杜子不疼.2 小时前
【Linux】基础IO(一):C 接口文件讲解
linux·c语言·开发语言·人工智能
猫猫的小茶馆3 小时前
【Linux 驱动开发】四. 平台总线驱动
linux·c语言·arm开发·驱动开发·嵌入式硬件·mcu·物联网
Yupureki3 小时前
《算法竞赛从入门到国奖》算法基础:入门篇-分治
c语言·开发语言·数据结构·c++·算法·贪心算法
代码游侠3 小时前
嵌入式开发代码实践——串口通信(UART)开发
c语言·开发语言·笔记·单片机·嵌入式硬件·重构
智码未来学堂3 小时前
C语言经典编程练习题(1)
c语言·开发语言
csdn_aspnet3 小时前
C语言常用算法深度解析:从基础到高级的实战艺术
c语言