CoreAudio框架使用如下声明的结构:
struct AudioBufferList
{
UInt32 mNumberBuffers;
AudioBuffer mBuffers[1]; // this is a variable length array of mNumberBuffers elements
};
typedef struct AudioBufferList AudioBufferList;
据我所知,这基本上是AudioBuffer
结构的可变长度集合。什么是正确的'这种结构的方法是malloc吗?
AudioBufferList *list = (AudioBufferList *)malloc(sizeof(AudioBufferList));
这会有用吗?
我已经在互联网上看过各种各样的例子,比如
calloc(1, offsetof(AudioBufferList, mBuffers) +
(sizeof(AudioBuffer) * numBuffers))
或
malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer) * (numBuffers - 1))
答案 0 :(得分:9)
这不是一个可变长度数组;这是一个'结构黑客'。标准(自C99)技术使用“灵活的阵列成员”,看起来如下:
struct AudioBufferList
{
UInt32 mNumberBuffers;
AudioBuffer mBuffers[]; // flexible array member
};
FAM的一个优点是你的问题“无关紧要”;为numBuffer
数组中的mBuffers
元素分配空间的正确方法是:
size_t n_bytes = sizeof(struct AudioBufferList) + numBuffer * sizeof(AudioBuffer);
struct AudioBufferList *bp = malloc(nbytes);
要回答您的问题,实际上malloc()
和calloc()
都会为作业分配至少足够的空间,但任何C标准都没有保证代码能够正常工作。话虽如此,编译器编写者知道这个成语已被使用,并且通常不会破坏它。
除非空间非常紧张,否则使用与FAM一样的表达式可能是最简单的;在最坏的情况下,你分配的空间比你绝对需要的多一些。升级代码以使用FAM时,它将继续工作。 calloc()
版本中使用的表达式也适用于FAM成员; malloc()
版本中使用的表达式会突然分配太少的空间。
答案 1 :(得分:3)
计算出你需要多少内存和malloc那个数量。例如,如果你想要另外9个AudioBuffers那么
list = malloc( sizeof *list + 9 * sizeof list->mBuffers[0] );
顺便说一下,整个构造都是不可移植的(如果行为超出mBuffers
的范围,则行为是未定义的,这是1),但它曾经相当普遍。
请注意,您不应转换malloc
返回的值。这样做没有任何好处,但是可以做到伤害。
有一个类似的标准结构;如果从1
的定义中删除AudioBufferList
(并且再添加一个malloc)。这被称为"灵活的阵列成员"。
答案 2 :(得分:2)
执行此操作的首选方法是在Core Audio Utility Classes中使用Apple提供的来自CAAudioBufferList.cpp的CAAudioBufferList::Create
函数。您可以在此处下载资源:
https://developer.apple.com/library/mac/samplecode/CoreAudioUtilityClasses/Introduction/Intro.html
以下是他们的实施:
AudioBufferList* CAAudioBufferList::Create(UInt32 inNumberBuffers)
{
UInt32 theSize = CalculateByteSize(inNumberBuffers);
AudioBufferList* theAnswer = static_cast<AudioBufferList*>(calloc(1, theSize));
if(theAnswer != NULL)
{
theAnswer->mNumberBuffers = inNumberBuffers;
}
return theAnswer;
}
void CAAudioBufferList::Destroy(AudioBufferList* inBufferList)
{
free(inBufferList);
}
UInt32 CAAudioBufferList::CalculateByteSize(UInt32 inNumberBuffers)
{
UInt32 theSize = SizeOf32(AudioBufferList) - SizeOf32(AudioBuffer);
theSize += inNumberBuffers * SizeOf32(AudioBuffer);
return theSize;
}