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++中,考虑使用类型安全的替代方案。

相关推荐
wangjialelele5 小时前
平衡二叉搜索树:AVL树和红黑树
java·c语言·开发语言·数据结构·c++·算法·深度优先
森G5 小时前
七、04ledc-sdk--------makefile有变化
linux·c语言·arm开发·c++·ubuntu
weixin_395448916 小时前
mult_yolov5_post_copy.c_cursor_0205
c语言·python·yolo
Z9fish6 小时前
sse哈工大C语言编程练习20
c语言·开发语言·算法
晓13137 小时前
第六章 【C语言篇:结构体&位运算】 结构体、位运算全面解析
c语言·算法
梵刹古音7 小时前
【C语言】 指针与数据结构操作
c语言·数据结构·算法
刘琦沛在进步7 小时前
【C / C++】引用和函数重载的介绍
c语言·开发语言·c++
VekiSon8 小时前
Linux内核驱动——杂项设备驱动与内核模块编译
linux·c语言·arm开发·嵌入式硬件
2的n次方_9 小时前
CANN Ascend C 编程语言深度解析:异构并行架构、显式存储层级与指令级精细化控制机制
c语言·开发语言·架构
_F_y10 小时前
C语言重点知识总结(含KMP详细讲解)
c语言·开发语言