有没有办法先声明然后在C中初始化一个数组?
到目前为止,我一直在初始化一个这样的数组:
int myArray[SIZE] = {1,2,3,4....};
但我需要做这样的事情
int myArray[SIZE];
myArray = {1,2,3,4....};
答案 0 :(得分:30)
在C99中,您可以使用复合文字与memcpy
memcpy(myarray, (int[]) { 1, 2, 3, 4 }, sizeof myarray);
(假设源的大小和目标的大小相同)。
在C89 / 90中,你可以通过声明一个额外的“源”数组来模拟它
const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */
int myArray[SIZE];
...
memcpy(myarray, SOURCE, sizeof myarray);
答案 1 :(得分:13)
不,你不能在一个陈述中将它们设置为任意值(除非作为声明的一部分完成)。
您可以使用代码执行此操作,例如:
myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 27;
:
myArray[99] = -7;
或(如果有公式):
for (int i = 0; i < 100; i++) myArray[i] = i + 1;
另一种可能性是保留一些 在声明时设置的模板并使用它们初始化你的数组,如:
static const int onceArr[] = { 0, 1, 2, 3, 4,..., 99};
static const int twiceArr[] = { 0, 2, 4, 6, 8,...,198};
:
int myArray[7];
:
memcpy (myArray, twiceArr, sizeof (myArray));
这样做的好处是(很可能)更快,并允许您创建比模板更小的数组。我已经在我必须快速重新初始化数组但是特定状态的情况下使用了这种方法(如果状态全部为零,我只使用memset
)。
您甚至可以将其本地化为初始化函数:
void initMyArray (int *arr, size_t sz) {
static const int template[] = {2, 3, 5, 7, 11, 13, 17, 19, 21, ..., 9973};
memcpy (arr, template, sz);
}
:
int myArray[100];
initMyArray (myArray, sizeof(myArray));
静态数组将(几乎可以肯定)在编译时创建,因此不会有运行时间成本,而memcpy
应该非常快,可能比1,229赋值语句更快,但肯定更少打字你的部分: - )。
答案 2 :(得分:4)
有没有办法先申报和 然后在C中初始化一个数组?
有!但没有使用你描述的方法。
您无法使用逗号分隔列表进行初始化,这仅在声明中允许。但是,您可以使用...
进行初始化myArray[0] = 1;
myArray[1] = 2;
...
或
for(int i = 1; i <= SIZE; i++)
{
myArray[i-1] = i;
}
答案 3 :(得分:2)
这是AndreyT接受的答案的附录,Nyan对不匹配的阵列大小的评论。我不同意他们将第五个元素的自动设置为零。应该 5 - 1,2,3,4之后的数字。因此,当我们尝试复制不同大小的数组时,我建议使用memcpy()的包装器来产生编译时错误:
#define Memcpy(a,b) do { /* copy arrays */ \
ASSERT(sizeof(a) == sizeof(b) && /* a static assert */ \
sizeof(a) != sizeof((a) + 0)); /* no pointers */ \
memcpy((a), (b), sizeof (b)); /* & unnecesary */ \
} while (0) /* no return value */
如果您的数组长度为1,则此宏将生成编译时错误。这可能是一个功能。
因为我们使用的是宏,所以C99复合文字似乎需要一对额外的括号:
Memcpy(myarray, ((int[]) { 1, 2, 3, 4 }));
这里ASSERT()是一个'静态断言'。如果您还没有自己的,我在许多平台上使用以下内容:
#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) /* version of ASSERT() with message */ \
enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
答案 4 :(得分:1)
为什么在申报时无法初始化?
您使用的是哪个C编译器?它支持C99吗?
如果它支持C99,您可以在需要的位置声明变量,并在声明时初始化它。
我能想到的唯一理由是不这样做是因为你需要声明它但是在使用它之前提前退出,因此初始化器会被浪费掉。但是,我怀疑任何这样的代码都没有应有的清晰组织,可以编写,因此不是问题。
答案 5 :(得分:0)
没有这样的特殊方法可以在声明一次后初始化数组。
仅限三个选项:
1。)在不同的行中初始化它们:
int array[SIZE];
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
//...
//...
//...
但那不是我想要的。
2。)使用for或while循环初始化它们:
for (i = 0; i < MAX ; i++) {
array[i] = i;
}
这是实现目标的最佳途径。
3。)如果您的要求是在一行中自行初始化数组,则必须至少定义一个带初始化的数组。然后将其复制到目标数组,但我认为这样做没有任何好处,在这种情况下,您应该在一行中定义和初始化数组。
我可以问你为什么要这么做?
答案 6 :(得分:0)
OP从问题中遗漏了一些重要信息,只是对答案进行了评论。
我需要在声明后进行初始化,因为会有所不同 根据条件,我的意思是这样的int myArray的[SIZE]; if(condition1){myArray {x1,x2,x3,...}} else if(condition2){myArray {y1,y2,y3,...}}。 。等等...
考虑到这一点,无论如何都需要将所有可能的数组存储到数据中,因此不需要(或需要)memcpy,只需要指针和2d数组。
//static global since some compilers build arrays from instruction data
//... notably not const though so they can later be modified if needed
#define SIZE 8
static int myArrays[2][SIZE] = {{0,1,2,3,4,5,6,7},{7,6,5,4,3,2,1,0}};
static inline int *init_myArray(_Bool conditional){
return myArrays[conditional];
}
// now you can use:
//int *myArray = init_myArray(1 == htons(1)); //any boolean expression
非内联版本在x86_64上提供了这个生成的程序集:
init_myArray(bool):
movzx eax, dil
sal rax, 5
add rax, OFFSET FLAT:myArrays
ret
myArrays:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
.long 6
.long 7
.long 7
.long 6
.long 5
.long 4
.long 3
.long 2
.long 1
.long 0
对于其他条件/数组,只需将myArrays中的2更改为所需的数字,并使用类似的逻辑来获取指向右数组的指针。
答案 7 :(得分:0)
初始化后无法一次性为数组赋值。 最好的选择是使用循环。
for(i=0;i<N;i++)
{
array[i] = i;
}
您可以硬编码并指定值,例如 - array[0] = 1
等。
如果您已将数据存储在数组中,也可以使用Memcpy。