在C中声明和初始化数组
有没有办法先声明,然后在C初始化一个数组?
到目前为止,我一直在这样初始化一个数组:
int myArray[SIZE] = {1,2,3,4....};
但我需要做这样的事情
int myArray[SIZE]; myArray = {1,2,3,4....};
在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);
不,您不能在一个语句中将它们设置为任意值(除非作为声明的一部分进行)。
你可以用代码来完成,比如:
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));
这具有(最有可能)更快的优点,并允许您创build比模板更小的数组。 我已经使用这种方法,我必须快速重新初始化一个数组,但到一个特定的状态(如果状态都是零,我只是使用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));
静态数组(几乎肯定)会在编译时创build,所以不会有运行时间的开销, memcpy
应该是快速的,可能比1,229赋值语句更快,但是在你的部分中键入的确很less:-) 。
有没有办法先声明,然后在C初始化一个数组?
有! 但不使用你描述的方法。
您不能使用逗号分隔列表进行初始化,只能在声明中进行。 你可以初始化…
myArray[0] = 1; myArray[1] = 2; ...
要么
for(int i = 1; i <= SIZE; i++) { myArray[i-1] = i; }
这是AndreyT接受的答案的附录,Nyan对不匹配数组大小的评论。 我不同意他们的第五个元素的自动设置为零。 它应该是5 – 1,2,3,4之后的数字。 所以当我们尝试复制不同大小的数组时,我会build议使用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,则此macros将生成编译时错误。这可能是一个function。
因为我们正在使用一个macros,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)}
你为什么不能在声明时初始化?
你正在使用哪个C编译器? 它支持C99吗?
如果它支持C99,则可以在需要的地方声明该variables,并在声明时初始化该variables。
唯一的借口,我可以想到不这样做是因为你需要声明它,但在使用它之前做一个提前退出,所以初始化将被浪费。 但是,我怀疑这样的代码并不像应该那样整齐地组织起来,可以这样写,所以这不是问题。
声明一次之后,就没有可以初始化数组的特殊方式。
只有三个选项:
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.)如果你的要求是在一行中初始化数组,你必须定义至less一个初始化的数组。 然后将其复制到目标数组中,但是我认为这样做没有任何好处,在这种情况下,您应该自己定义并初始化您的数组。
我可以问你为什么你想这样做?
OP在这个问题上留下了一些重要的信息,只是在评论中给出了答案。
我需要声明后初始化,因为将根据条件不同,我的意思是这样的int myArray [SIZE]; if(condition1){myArray {x1,x2,x3,…}} else if(condition2){myArray {y1,y2,y3,…}}。 。 等等…
考虑到这一点,所有可能的数组将需要存储到某处的数据,所以不需要memcpy(或所需),只需要一个指针和二维数组。
//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
对于附加的条件/数组,只需将myArray中的2更改为所需的数字,并使用类似的逻辑来获取指向右边数组的指针。
在初始化之后,不可能一次性为数组赋值。 最好的select是使用循环。
for(i=0;i<N;i++) { array[i] = i; }
你可以硬编码和赋值,如 – array[0] = 1
等等。
如果您已经将数据存储在数组中,也可以使用Memcpy。