我这个代码最大的问题是在这条线:
fread (buffer,sizeof(int),4000000,fp);
这条线实际上引入了一个重要的问题列表。首先,不能保证您正在阅读的文件已成功打开。正如其他人所指出的那样,您需要比较fp
和NULL
来作出保证。其次,似乎我经常强调这种方式:你真的应该检查返回值。这适用于所有标准C函数,而不仅仅是fopen和fread。
返回值fread告诉您有多少项实际上被读取。假设你要求四百万int
秒,而该文件只包含两个。返回值会告诉你只有两个int
被读取。
现在,到大的东西!让我们首先考虑sizeof(int)
在不同的实现上有所不同。您的系统可能会读取四个字节,而另一个可能读取两个字节,但可能读取八个字节。这只是整数表示可能不同的基本方式。
让我们考虑一个更微妙的,但同样的破坏性方式整数表示可能会有所不同:假设你的int
s为四个字节,用最左边的位是最低显著位。另一台机器可能使用最左边的位作为至少的重要位。同样,考虑字节顺序排列,这是字节的顺序。
假设您的int
s是32位,并且它们表示-(1 << 31)
和(1 << 31)
之间的值,这意味着没有填充位。另一个系统可能会使用具有16位填充的32位整数,这意味着它可能仅表示-(1 << 16)
和(1 << 16)
之间的值。假设这些填充位是奇偶校验位,以确保RAM正常运行(例如Intel Xeon服务器)。现在你有一种情况,你的服务器告诉你你的内存有问题,如果没有。
您的代码应该从您的文件用于存储整数的整数表示形式显式转换为计算机本机使用的任何表示形式。在将整数写入文件时,需要确保您明确地将您的实现表示转换为表示表示的。同样,当从文件中读取整数时,代码应该明确地将该表示转换为您的实现表示。例如,让我们假设您的int
值不会超出-32767
或32767
(16位有符号整数,1的补码)。使用两个字节来表示这种情况是可移植的,但您需要明确定义该整数的符号和表示形式。写入时,可以提取符号和绝对值,然后将sign * 128 + absolute_value/256
和absolute_value % 256
写入文件。阅读时,您会提取符号位,然后相乘并添加以重建您的值。
让我们考虑您的文件据称是4MB,而你正在阅读sizeof (int) * 4000000
值。 4MB是0x400000
,而不是sizeof (int) * 4000000
。我想你真的想将沿着线的东西是什么:
unsigned char *foo = malloc(0x400000); /* 4MB */
/* XXX: Handle malloc errors here */
assert(foo != NULL);
FILE *fp = fopen("file.bin", "rb");
/* XXX: Handle fopen errors here */
assert(fp != NULL);
size_t num_bytes_read = fread(foo, 1, 0x400000, fp);
/* XXX: Transform the bytes into integers */
free(foo);
我的问题是,它依赖于一个4MB缓存只读取和转换字节为整数。这个任务根本不需要缓冲区!
FILE *fp = fopen("file.bin", "rb");
/* XXX: Handle fopen errors here */
assert(fp != NULL);
for (;;) {
int x = fgetc(fp);
/* XXX: Handle fgetc errors here */
assert(x >= 0);
int y = fgetc(fp);
/* XXX: Handle fgetc errors here */
assert(y >= 0);
/* XXX: Transform the characters in x and y into the int values */
};
free(foo);
无论你需要存储的地方不是在问题中指定的转化价值。如果你不需要,那么我的下一个问题就是使用一个数组,当你只能读一个项目,处理它,然后移动到下一个项目。
你知道平均堆栈大小是否在1到4兆字节之间?你有几乎16兆字节的堆栈。我很惊讶你的程序甚至加载。 – 2013-04-25 08:15:31
我在C编程中是全新的,如果它可能向我展示如何完成任务,请.. – 2013-04-25 08:19:23
然后这里有几个其他有用的提示(与你的问题无关,但仍然很好):在C中从来没有一个声明函数时为空参数列表。这意味着该函数需要一个未指定数量的未指定参数。当用于'main'时,它实际上不符合规范。如果你想要一个没有参数的函数使用'void',如'int main(void)...'所示。你还声明'main'返回一个'int'(这是正确的),但你实际上并没有返回任何东西。你要么需要调用'exit'或'return'值(零意味着没有错误)。 – 2013-04-25 08:24:14