动态对象(C指针处理)传递给函数时

时间:2018-01-29 13:46:06

标签: c pointers memory-management arguments

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中,我还没有理解这一点。

3 个答案:

答案 0 :(得分:1)

  1. 取决于您自己的API文档。如果您已明确声明该函数将接受空指针,则应检查它们。如果没有,则不能进行检查。

  2. 第一种形式由于显而易见的原因而无法运作,请参阅Dynamic memory access only works inside function。您可以通过指针指针或返回值返回数据。要么没事。通常,专业API的返回值:s保留用于结果/错误代码。

  3. 根据您自己的API文档。最粗略的错误处理是返回NULL或类似。更多详细的功能包含许多可能出错的内容,通常使用枚举或其他自定义类型。

  4. 取决于该功能的用途。执行内存分配的代码负责清理。一般情况下,如果可能的话,最好将分配留给呼叫者,但有时候不是这样,就像使用"不透明指针"或其他一些ADT。然后ADT应该在内部处理分配/释放,就像在C ++中一样。区别在于C只有穷人的构造函数/析构函数" - 必须明确调用这些函数。

  5. 不是真的,尽管有各种各样的"事实上的"标准。您可以研究如何在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

发布的不透明对象