我在 C 中有一个大型数组(如果这有区别的话,不是 C++)。我希望将所有成员初始化为相同的值。
我记得曾经知道一种简单的方法来做到这一点。虽然我可以在我的情况下使用 memset()
,但是否有一种内置于 C 语法中的方法来实现这一点呢?
我在 C 中有一个大型数组(如果这有区别的话,不是 C++)。我希望将所有成员初始化为相同的值。
我记得曾经知道一种简单的方法来做到这一点。虽然我可以在我的情况下使用 memset()
,但是否有一种内置于 C 语法中的方法来实现这一点呢?
除非该值为0(在这种情况下,您可以省略初始化程序的某些部分,相应的元素将被初始化为0),否则没有简单的方法。
但是不要忽视显而易见的解决方案:
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
具有缺失值的元素将被初始化为0:
int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...
因此,这将使所有元素初始化为0:
int myArray[10] = { 0 }; // all elements 0
C++中,空初始化列表也会将每个元素初始化为0。在C23之前的C语言中不允许这样做:
在C++中,空的初始化列表将会默认将每个元素初始化为0。而在C语言中,空的初始化列表则是非法的,直到C23版本才支持。
int myArray[10] = {}; // all elements 0 in C++ and C23
请记住,如果未指定初始化程序,则具有静态存储期的对象将初始化为0:
static int myArray[10]; // all elements 0
而且“0”并不一定意味着“所有位都是零”,因此使用上述方法比memset()更好、更具可移植性。(浮点数值将被初始化为+0,指针为null值等)
int myArray[] = {[3] = 123, [7] = 23};
这将给你 {0, 0, 0, 123, 0, 0, 0, 23}
。 - akofink如果您的编译器是GCC,您可以使用以下“GNU扩展”语法:
int array[1024] = {[0 ... 1023] = 5};
请查看详细说明:http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
int foo1 = 1, foo2 = 1, ..., foo65536 = 1;
,你会得到相同的大小增加。 - qrdlbool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}
,但我不确定这比完整形式更易读。 - user67416为了在静态初始化大型数组时使用相同的值,而不需要多次复制和粘贴,可以使用宏:
对于静态初始化大型数组并使用相同值,可以使用宏来简化操作:
#define VAL_1X 42
#define VAL_2X VAL_1X, VAL_1X
#define VAL_4X VAL_2X, VAL_2X
#define VAL_8X VAL_4X, VAL_4X
#define VAL_16X VAL_8X, VAL_8X
#define VAL_32X VAL_16X, VAL_16X
#define VAL_64X VAL_32X, VAL_32X
int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };
如果你需要更改值,那么你只需要在一个地方进行替换。
(由Jonathan Leffler提供)
你可以轻松地将此通用化:
#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */
可以使用以下方式创建变体:
#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */
可以与结构体或复合数组一起使用的。
#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)
struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };
宏名称可以商议。
VAL_1X
不是单个整数而是一个列表,您仍然可以使用此方法。像Amigable所说的那样,这也是嵌入式系统中定义EEPROM或Flash存储器初始值的方法。在这两种情况下,您都不能使用 memset()
。 - Martin Scharrer如果您想确保数组的每个成员都被明确初始化,只需在声明中省略维度:
int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
编译器将从初始化列表中推断出数组的维度。不幸的是,对于多维数组,只有最外层的维度可以省略:
int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
没问题,但是
int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
不是。
int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
- Praveen Gowda I Vchar const *array[] = {...};
或者甚至是char const *const array[] = {...};
,不是吗? - Jonathan Lefflerint i;
for (i = 0; i < ARRAY_SIZE; ++i)
{
myArray[i] = VALUE;
}
我认为这比之前更好。
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5...
防止数组大小发生改变。
i
? - user16217248您可以像上面详细介绍的那样完成整个静态初始化程序,但是如果数组大小发生变化(如果您未添加适当的额外初始化程序,则数组扩大时会出现垃圾数据),这可能会让人沮丧。
memset方法会在运行时给你带来一些负担,但正确使用不会对代码大小产生影响,但仍然无法免除数组大小变化所带来的问题。我建议在数组大小超过几十个元素时,几乎所有情况下都使用此解决方案。
如果真的很重要,必须静态声明数组,那么我会编写一个编写程序的程序,并将其作为构建过程的一部分。
memset
初始化数组的用法上加入一些示例? - Sopalajo de Arrierez我知道原问题明确提到了C而不是C++,但如果你(像我一样)在这里寻找C++数组的解决方案,这里有一个巧妙的方法:
如果你的编译器支持fold表达式,你可以使用模板魔法和std::index_sequence
生成一个初始化列表,并用你想要的值填充它。你甚至可以把它变成constexpr
并感觉像个大佬:
#include <array>
/// [3]
/// This functions's only purpose is to ignore the index given as the second
/// template argument and to always produce the value passed in.
template<class T, size_t /*ignored*/>
constexpr T identity_func(const T& value) {
return value;
}
/// [2]
/// At this point, we have a list of indices that we can unfold
/// into an initializer list using the `identity_func` above.
template<class T, size_t... Indices>
constexpr std::array<T, sizeof...(Indices)>
make_array_of_impl(const T& value, std::index_sequence<Indices...>) {
return {identity_func<T, Indices>(value)...};
}
/// [1]
/// This is the user-facing function.
/// The template arguments are swapped compared to the order used
/// for std::array, this way we can let the compiler infer the type
/// from the given value but still define it explicitly if we want to.
template<size_t Size, class T>
constexpr std::array<T, Size>
make_array_of(const T& value) {
using Indices = std::make_index_sequence<Size>;
return make_array_of_impl(value, Indices{});
}
// std::array<int, 4>{42, 42, 42, 42}
constexpr auto test_array = make_array_of<4/*, int*/>(42);
static_assert(test_array[0] == 42);
static_assert(test_array[1] == 42);
static_assert(test_array[2] == 42);
static_assert(test_array[3] == 42);
// static_assert(test_array[4] == 42); out of bounds
static void
unhandled_interrupt(struct trap_frame *frame, int irq, void *arg)
{
//this code intentionally left blank
}
static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = {
[0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL},
};
参见:
指定初始化
那么问题来了:什么时候可以使用 C 扩展?
上面的代码示例是在嵌入式系统中,永远不会被其他编译器看到。
array = initial_value
在你喜欢的数组可处理语言中(我喜欢Fortran,但也有其他语言),并将其链接到你的C代码。你可能想要将其包装成一个外部函数。
enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };
和struct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };
。如果删除省略号…
,这些片段可以在C99或C11下编译通过。 - Jonathan Lefflermemset()
特定讨论:https://dev59.com/qmw05IYBdhLWcg3wfx80 我认为它只适用于0。 - Ciro Santilli OurBigBook.commemset()
只适用于值为0
、UINT_MAX
和元素大小为char
的数组。 - user16217248