每当我想使用C读取或写入二进制文件时,我都会使用fread()
和fwrite()
函数。它们需要作为参数读取或写入的数据的字节,因此我使用sizeof()
函数。现在的问题是:
书中说我应该声明一个这样的函数:
fread(&variable,sizeof(TYPE_OF_VAR),quantity,file);
我使用以下语句,该语句大部分时间都有效,但并非总是如此:
fread(&variable,sizeof(VARIABLE),quantity,file);
为什么它有时会起作用,但有时却不起作用? 它取决于变量(int,char等)的类型 吗? 它取决于我使用的数据的数量吗?
答案 0 :(得分:2)
要记住的是sizeof
基于编译器在编译时对类型的了解(暂时忽略VLA)。如果给它一个变量,它将使用该变量的类型。
所以,我唯一能想到它不会像你期望的那样工作的是指针。
基本上归结为:
int x[5];
int *y = &x[0];
int *p = malloc(sizeof(int) * 5);
sizeof(x); // == sizeof(int) * 5
sizeof(y); // == sizeof(int *)
sizeof(p); // == sizeof(int *)
在处理函数时这很棘手,因为当传递给函数时,数组衰减指针。另请注意,其中所有3个都完全等效:
int func(int *p);
int func(int p[5]);
int func(int p[]);
在所有3中,p是指针,而不是数组。
答案 1 :(得分:1)
有关堆与堆栈的讨论,请参阅此Stack Overflow问题: What and where are the stack and heap 。
堆元素上的 sizeof()
(如指针)将返回指针的大小,而不是指针可以存储的元素数。
但是,堆栈元素上的sizeof()
:数组或const char *
将返回数组或字符串的长度。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 100
int main(int argc, char *argv[])
{
char *a = NULL;
char b[10] = "abcdefghi";
printf("sizeof(b): %zu\n", sizeof(b));
a = malloc(LENGTH + 1);
if (a) {
*(a + LENGTH) = '\0';
memset(a, ' ', LENGTH);
fprintf(stdout, "a (before memcpy):\t[%s]\n", a);
printf("sizeof(a), before: %zu\n", sizeof(a));
memcpy(a, b, sizeof(b) - 1);
fprintf(stdout, "a (after memcpy):\t[%s]\n", a);
printf("sizeof(a), after: %zu\n", sizeof(a));
free(a);
}
return EXIT_SUCCESS;
}
编译:
$ gcc -Wall sizeofTest.c -o sizeofTest
输出:
$ ./sizeofTest
sizeof(b): 10
a (before memcpy): [ ]
sizeof(a), before: 8
a (after memcpy): [abcdefghi ]
sizeof(a), after: 8
在我的平台上,char *
指向一个占用8个字节的内存地址。
答案 2 :(得分:0)
它将始终有效。
int main()
{
char a[10];
int b[10];
printf("%d %d %d %d %d %d",sizeof(char),sizeof(int), sizeof(a),sizeof(b), sizeof(a[0]), sizeof(b[0]) );
}
试试上面的代码。你应该看到(取决于编译器,我的char为1byte,整数为4字节)1,4,10,40,1,4
对于fread或fwrite或您使用它的任何地方都没有区别。