我正在用C学习数组,我正在尝试使用冒泡算法。
我做(在主要功能中):
int main{
srand(time(NULL)); //Randomize
int SIZE = (rand() % 20) + 1;
int number[ SIZE ] = { 0 };
...
}
但是编译器说:variable-sized object may not be initialized
。
我需要声明一个数组,在其中插入N个随机生成的数字,然后 通过冒泡排序算法对它们进行排序。
我使用" stdio.h"和" time.h"。
为什么,如果我尝试将所有数字的数组初始化为0,编译器会出错?
如果我擦除= { 0 };
,编译器不会给出错误,但程序运行不正常
这是我的代码: http://pastebin.com/uBaYWXbR
感谢大家! :) 对不起,如果我的英语不好。
答案 0 :(得分:6)
编译时不知道number
的大小,因此编译器无法为其生成初始化程序。您可以使用memset
自行初始化它,也可以使数组的大小为编译时常量。
memset(number, 0, SIZE*sizeof(int));
当您完全省略初始化时,您的程序可能会失败,因为它假设数组已初始化为0,而它根本没有初始化并包含任意值。
答案 1 :(得分:5)
错误消息足够清楚:您可能无法初始化VLA。所以简单地替换这个陈述
int number[ SIZE ] = { 0 };
的
int number[ SIZE ];
如果您希望数组的所有元素都等于0,那么您可以使用标头memset
中声明的标准C函数<string.h>
。例如
int number[ SIZE ];
memset( number, 0, sizeof( number ) );
这是一个完整的例子
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(void)
{
srand( ( unsigned int )time( NULL ) );
int SIZE = rand() % 20 + 1;
int a[SIZE];
memset( a, 0, sizeof( a ) );
return 0;
}
至于你的程序,那么即使是第一个循环也是无效的
for(i=0; i <= SIZE; i++);
{
number[ i ] = (rand() % 100) + 1;
}
首先,您必须删除for语句末尾的分号,并且循环的条件应为
i < SIZE
因此它看起来像
for ( i = 0; i < SIZE; i++ )
{
number[ i ] = rand() % 100 + 1;
}
此外,我还没有看到你的程序中有泡泡排序的地方。:)
答案 2 :(得分:1)
有不同种类的分配。
一种方法是在源代码中声明分配。然后编译器将在目标文件中创建一个变量(名称引用),并确保下一个名称引用距离内存距离足够远,以保证设置另一个变量不会写入预先分配的空间数组。
在编译时不知道数组的大小时,无法执行此操作。通过使用变量,无法保证大小,编译器无法进行上述计算。
您需要显式处理分配,因为计算的&#34;元素的值只计算了#34;变量将被称为程序运行时。
为此,请求操作系统分配一些大小。请注意,此大小通常分配在堆上,该堆是程序负责指示何时使用内存以及何时释放内存的内存区域。您将使用
请求内存memset(number, 0, SIZE*sizeof(int));
将返回一个称为指针的数字,该数字表示memeset
命令保留的第一个元素的地址。它的类型是
void *
有时候这颗恒星会被移动一下,但要记住它是虚空的一部分。要阅读这些类型,请从右到左阅读它们,替换为&#34;指针&#34;对于明星。
(a pointer to no particular type)
由于您需要多个整数,因此您知道分配的内存可以包含整数,因此将返回的地址强制转换为
(int *)
表示指向多个整数的指针。
int* number = (int*)malloc(SIZE*sizeof(int));
然后你可能应该把内存归零,因为如果你还记得,你现在负责初始化,因为这是堆内存。
memset(number, 0, SIZE*sizeof(int));
将写入字节&#39; 0&#39;到int的byte-size指示的所有字节乘以你请求的int元素数(SIZE)。
最后,您现在可以使用类似于使用int number [SIZE]的方式使用已分配的内存。语法类似于
number[4] = 5;
或更多&#34;指针&#34;面向语法
*(number + 4) = 5;
我强烈建议你专门使用数组语法,直到你最终写出一些与指针相关的东西而不是它指向的值。您还可以使用语法
读取数组int value = number[4];
或者再次,在更多面向指针的语法
中int value = *(number + 4);
请记住,您完全控制在这里,如果指定SIZE为5,则只有索引{0,1,2,3,4}有效。如果你不小心打电话给number[12]
,目前还不清楚程序会做什么。如果你很幸运,它会崩溃,如果你运气不好,它会搞乱别的东西,使程序的其他部分崩溃或者甚至不会崩溃,但会使程序中的某些数据发生不适当的变化。
要释放内存,请执行
free(number);
无法释放堆内存被称为内存泄漏,内存泄漏问题很难修复,因此尝试在单个代码块中将分配与frees对齐是一种很好的编程习惯,像这样:
int function(... params ...) {
char* name = (char*)malloc(...);
... do stuff ....
free(name);
}
如果你不能这样做,那可能是因为你的分配延迟到你需要之前
int caller(...) {
char* name = getName(...);
printf("%s", name);
// should name be freed?
}
更好的策略
int caller(...) {
char* name = (char*)malloc(getNameSize());
fillName(name);
printf("%s", name);
free(name);
}
在你学习正确的内存管理并且通常不再使用指针之前,我建议你不要尝试操作指针值。