只是想知道分配内存和 fread()
的最合理方法是什么?来自 C 文件中的数组数据。
首先解释一下:
int32_t longBuffer;
现在,当读取 longBuffer 时,代码可以如下所示:
fread(&longBuffer, sizeof(longBuffer), 1, fd); //version 1
fread(&longBuffer, sizeof(int32_t), 1, fd); //version 2
在这两者中,我想说版本 1 更安全,因为如果 longBuffer
的类型更改(比如说 int16_t
),不必担心忘记更新 fread()
。的sizeof()
使用新类型。
现在,对于数据数组,代码可以写为:
//listing 1
int8_t *charpBuffer=NULL; //line 1
charpBuffer = calloc(len, sizeof(int8_t)); //line 2
fread(charpBuffer, sizeof(int8_t), len, fd); //line 3
但是,这展示了第一个示例中暴露的问题:人们必须担心不要忘记同步 sizeof(<type>)
更改 charpBuffer
类型时的说明(假设从 int8_t*
到 int16_t*
)。
因此,人们可以尝试写:
fread(charpBuffer, sizeof(charpBuffer[0]), len, fd); //line 3a
作为一个更安全的版本。这应该有效,因为在第 2 行分配之后,写入 charpBuffer[0]
完全有效。
此外,还可以写:
fread(charpBuffer, sizeof(*charpBuffer), len, fd); //line 3b
但是,尝试对内存分配执行相同的操作,例如:
charpBuffer = calloc(len, sizeof(charpBuffer[0])); //line 2a
虽然语法更好,但表现出未定义的行为,因为在这个阶段,写 charpBuffer[0]
结果导致取消引用 NULL 指针。另外,写:
charpBuffer = calloc(len, sizeof(*charpBuffer)); //line 2b
存在同样的问题。
那么,现在的问题是:
代码行“第 2b 行”和“第 3b 行”是否正确(忽略此问题的未定义行为)或者有一些我错过的技巧。他们的“更明智”的对应物,例如“line 2a/3a”和“line 2/3”?
编写“ list 1”代码的最安全的方法是什么,同时避免任何形式的未定义行为?
编辑(为了澄清某些方面):
讨论方向错误。编译时与运行时的问题是一回事(我也希望对此有一个标准保证,但这不是主题)。 sizeof(NULL 取消引用) 的未定义行为的问题是另一个问题。即使在编译时,我也不相信标准保证这不会导致 UB。该标准是否提供任何保证?
最佳答案
您似乎对 sizeof
运算符有错误的想法。该运算符在编译时求值,因此您传递给它的表达式在程序运行时没有机会求值。
在 sizeof
运算符的上下文中,*charBuffer
和 charBuffer[0]
都是安全的,无论它们之前使用还是使用当相应的内存可用后。这只是避免键入类型名称的一种方法,因此可以减少重复。
编辑
如下所述,在编译时评估 sizeof
的规则有一个值得注意的异常(exception)(尽管它与问题中发布的代码无关)。由于 C 和 C++ 允许可变长度数组作为自动变量,因此对这些数组应用 sizeof
实际上可能会涉及一些运行时开销。
关于您对未定义行为的担忧,我认为这是没有根据的:
int vla[n]; // declare a variable-length array of length n
/* The compiler will produce code using the value of n prior to
declaring the array to compute its size. */
x = sizeof(vla);
/* The space for the array is already available, so the expression
*vla is not UB anywhere (except if n is 0). Furthermore, n is
not involved in the computation and the operator can be evaluated at
compile-time. */
y = sizeof(*vla);
z = sizeof(vla[0]); // same thing
关于c - 在 C 中使用 fread() 分配内存和读取数组的最便携方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15131338/