用数组声明,C

时间:2014-08-02 19:32:41

标签: c arrays algorithm

我正在用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

感谢大家! :) 对不起,如果我的英语不好。

3 个答案:

答案 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);
}

在你学习正确的内存管理并且通常不再使用指针之前,我建议你不要尝试操作指针值。