C语言 一种动态计算传递给函数的不同数组大小的方法



所以我理解数组衰减到指针,但没有一种有效的方法来计算数组大小,特别是使用复合文字?

假设我将不同大小的数组传递给函数;理想情况下,我会使用一种动态确定大小的方法,而无需我强化数字,但我不能在函数中这样做。剩下的另一个选项是调用者代码,其中我无法真正更改每个函数调用的静态数组

foo((uint8_t) {1,2});
foo((uint8_t) {1});

我建议的方法是使用标准初始值设定项语法声明命名对象。

static const uint8_t my_array[] = {1,2};

这样你就可以通过my_arraysizeof my_array. 使用复合文本可能看起来更方便,但除非它们很小,否则会降低效率,因为无法创建具有静态持续时间的 const 限定复合文本。 创建具有自动持续时间的对象并将其地址传递给外部代码通常使符合要求的编译器必须在每次使用对象时实际创建和填充对象,即使它们被声明为const,而使用静态持续时间 const 限定的对象可以避免此类问题。

Chris Dodd建议的一个变体是将函数包装在宏中:

void real_foo(uint8_t *arr, size_t len);
#define foo(...) real_foo((uint8_t[]) __VA_ARGS__, (sizeof (uint8_t[]) __VA_ARGS__)/sizeof(uint8_t));
// ...
foo({1});
foo({1,2});

试穿神螺栓

请注意,使用可变参数宏来解决{1,2}被解析为两个宏参数的事实。

对于略有不同的语法,您也可以在宏定义中编写{ __VA_ARGS__ },以便您可以将其调用

foo(1);
foo(1,2);

你也可以宏化supercat的解决方案,如果你愿意使用gcc/clang语句表达式(一个非标准的C扩展(:

#define foo(...) ({ static const uint8_t my_array[] = { __VA_ARGS__ }; real_foo(my_array, sizeof(my_array) / sizeof(uint8_t)); })

或者,如果real_foo()返回void,则可以执行以下操作,即标准C:

#define foo(...)  do { static const uint8_t my_array[] = { __VA_ARGS__ }; real_foo(my_array, sizeof(my_array) / sizeof(uint8_t)); } while (0)

do/while会吃分号的地方。

当然,这假设real_foo()不需要修改数组。 如果是这样,即使没有const,这也不起作用,因为如果再次执行代码,数组将不会重新初始化。

另一种选择是重新设计您的函数,以便不需要告诉它数组的大小。 例如,如果有一些值不能作为数组的条目,则可以将其用作哨兵:

foo((uint8_t []){1, 2, 0xff});

您的示例不是有效的 C 语法,尽管 gcc 接受它并带有警告

warning: excess elements in scalar initializer

然后继续仅传递大括号中的第一个值作为参数。 您可以通过添加[]来执行此操作,但随后您将丢失大小,如您所注意的:

foo((uint8_t[]) {1,2});

您可以计算大小并将其作为第二个参数传递,但这需要复制静态数组:

foo((uint8_t[]) {1,2}, sizeof((uint8_t[]) {1,2})/sizeof(uint8_t));

如果您将其定义为宏或变量,这可能是可以接受的:

#define ARR (uint8_t[]) {1,2}
// or
uint8_t ARR[] = {1, 2};
foo(ARR, sizeof(ARR)/sizeof(ARR[0]));

最新更新