You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Apple CoreAudio中AudioBufferList可变长数组实现及自定义代码报错问题

解读CoreAudio中可变长数组的实现,以及你的测试代码问题

你看到的AudioBufferList是C语言里非常经典的结构体hack(也叫柔性数组的早期实现方案),这种写法在C99标准正式引入柔性数组前就被广泛使用,Clang、GCC这类主流编译器都对它提供兼容支持,所以CoreAudio的代码能正常工作。

为什么CoreAudio的写法有效?

这个结构体的核心思路不是单独给mBuffers分配内存,而是一次性分配足够容纳结构体本身 + 额外数组元素的整块内存。比如你需要存储NAudioBuffer对象时,实际分配的内存大小是:

sizeof(AudioBufferList) + (N - 1) * sizeof(AudioBuffer)

因为结构体里已经自带了1个AudioBuffer的空间,所以只需要额外补上N-1个元素的空间。分配完成后,你可以直接通过mBuffers[index]访问第index个元素(只要index < mNumberBuffers),编译器会自动计算正确的内存偏移位置。

你的测试代码为什么报错?

你犯了两个关键错误:

  • 数组名o.array不可修改的左值,不能用=直接赋值(这就是编译错误"Array type 'int [1]' is not assignable"的直接原因)
  • 这种可变长数组的用法不是给数组单独分配内存,而是要把结构体和数组空间作为一个整体分配

修正后的测试代码示例

#include <iostream>
#include <cstdlib>

struct Object {
    int size;
    int array[1]; // 老风格的可变长数组写法
};

int main(int argc, const char * argv[]) {
    int desiredSize = 2;
    // 分配足够的内存:结构体大小 + 额外(desiredSize-1)个int的空间
    Object* o = (Object*)malloc(sizeof(Object) + (desiredSize - 1) * sizeof(int));
    if (!o) { // 别忘了检查内存分配是否成功
        std::cerr << "malloc failed!" << std::endl;
        return 1;
    }

    o->size = desiredSize;
    // 给数组元素赋值
    o->array[0] = 100;
    o->array[1] = 200;

    // 验证结果
    for (int i = 0; i < o->size; ++i) {
        std::cout << "array[" << i << "] = " << o->array[i] << std::endl;
    }

    free(o); // 记得释放内存
    return 0;
}

补充:C99标准的柔性数组写法

现在C99及以后的标准推荐用柔性数组(flexible array member),写法更清晰,不需要指定[1]

struct Object {
    int size;
    int array[]; // 标准柔性数组,本身不占结构体空间
};

分配内存时直接用sizeof(Object) + desiredSize * sizeof(int)即可。CoreAudio用[1]的写法是为了兼容更老的、不支持C99的编译器。

内容的提问来源于stack exchange,提问作者bobobobo

火山引擎 最新活动