1)函数是否应检查每个指针参数是否为NULL?
void do_stuff(char** object1, char** object2, ...) {
if (object1 == NULL) {
return;
}
if (object2 == NULL) {
return;
}
...
2)当一个函数创建一个动态对象时,它应该返回一个指向新创建的对象的指针,还是应该将它分配给它的参数?
void allocate_object(char** object);
或
char** allocate_object(void);
3)当一个函数用于分配一个对象而没有这样做时,如何通知调用者结果?
return -1;
或
object = NULL;
4)谁(通常)对指针参数负责(检查,免费):一个函数或它的调用者?
5)是否有任何指南或资源可以回答类似的问题?
使用C ++及其类,每个对象都拥有它的所有者。这与RAII和异常处理一起帮助我回答我的问题。在C中,我还没有理解这一点。
答案 0 :(得分:1)
取决于您自己的API文档。如果您已明确声明该函数将接受空指针,则应检查它们。如果没有,则不能进行检查。
第一种形式由于显而易见的原因而无法运作,请参阅Dynamic memory access only works inside function。您可以通过指针指针或返回值返回数据。要么没事。通常,专业API的返回值:s保留用于结果/错误代码。
根据您自己的API文档。最粗略的错误处理是返回NULL或类似。更多详细的功能包含许多可能出错的内容,通常使用枚举或其他自定义类型。
取决于该功能的用途。执行内存分配的代码负责清理。一般情况下,如果可能的话,最好将分配留给呼叫者,但有时候不是这样,就像使用"不透明指针"或其他一些ADT。然后ADT应该在内部处理分配/释放,就像在C ++中一样。区别在于C只有穷人的构造函数/析构函数" - 必须明确调用这些函数。
不是真的,尽管有各种各样的"事实上的"标准。您可以研究如何在Windows API等大型库中完成它。
答案 1 :(得分:1)
1)应根据上下文使用空检查。
除非NULL是预期的解决方案,否则最好在函数中保留空值检查。
2)最好将错误代码作为结果返回,如下面的函数。 如果我们想要传递一些额外的信息以及指针参数,它总是更好地返回错误或状态代码。
int32_t allocate_object(char* object);// error code type will be int32_t
3)Enums比int更好地完成这项工作。创建一个包含各种错误案例的枚举。
enum etype_error
{
E_SUCCESS = 0,
E_INVALID_INPUT = -1,
E_FILE_NOT_FOUND = -2,
...
};
4)在c和c ++中,没有人负责指针分配&解除分配,你可以随时随地做到。 它只是一个很好的做法,可以在分配它的同一块中解除分配。
因此,调用者自己最好释放指针。
5)我不确定C语言的好参考教科书。 但是对于c ++来说,Scott Meyers的Effective c ++和More Effective C ++是很好的书籍,有很多指导和编程实践。我相信它会有很大的帮助。
答案 2 :(得分:0)
只是Lundin对第4点的回答的补充:
4)谁(通常)对指针参数负责(检查,免费):一个函数或它的调用者?
最好的情况是分配和解除分配可以在同一个功能中发生。您可以事先知道数组的大小,或者如果您只需要分配一个完整的结构,您可以在调用者中进行分配并将已分配的(但未填充的内存)传递给被调用者。但有时实际大小只能在被调用函数中计算。在这种情况下,被调用者负责分配,并返回分配的bloc作为其返回值或指向指针的指针(双星指针)。然后调用者获得所有权(因为创建者函数已经结束),并且可以直接(使用free
调用)或通过调用关闭函数来解除分配。
后一种情况的一个例子是FILE
流。它是一个由fopen
初始化并由fclose