如何从函数返回一个整数

时间:2010-04-18 23:57:36

标签: c

哪种风格更好?

int set_int (int *source) {
   *source = 5;
   return 0;
}

int main(){
   int x;
   set_int (&x);
}

OR

int *set_int (void) {
    int *temp = NULL;
    temp = malloc(sizeof (int));
    *temp = 5;
    return temp;
}

int main (void) {
    int *x = set_int ();
}

为了获得更高级别的编程背景,我得说我更喜欢第二个版本。任何提示都会非常有帮助。还在学习C。

9 个答案:

答案 0 :(得分:6)

都不是。

// "best" style for a function which sets an integer taken by pointer
void set_int(int *p) { *p = 5; }

int i;
set_int(&i);

或者:

// then again, minimise indirection
int an_interesting_int() { return 5; /* well, in real life more work */ }
int i = an_interesting_int();

仅仅因为更高级别的编程语言在幕后进行了大量的分配,意味着如果你不断添加更多不必要的分配,你的C代码将变得更容易编写/读取/调试: - )

如果你确实需要一个用malloc分配的int,并使用一个指向那个int的指针,那么我会选择第一个(但是没有修复):

void set_int(int *p) { *p = 5; }

int *x = malloc(sizeof(*x));
if (x == 0) { do something about the error }
set_int(x);

请注意,函数set_int 的方式相同。它不关心它设置的整数来自何处,无论是堆栈还是堆,谁拥有它,它是否已存在很长时间或是否是全新的。所以它很灵活。如果你想编写一个执行两项操作的函数(分配一些东西并设置值),那么当然你可以使用set_int作为构建块,也许是这样的:

int *allocate_and_set_int() {
    int *x = malloc(sizeof(*x));
    if (x != 0) set_int(x);
    return x;
}

在真实应用的环境中,您可能会想到一个比allocate_and_set_int更好的名字...

答案 1 :(得分:2)

一些错误:

int main(){
 int x*;  //should be int* x; or int *x;
 set_int(x);
}

此外,您在第一个代码示例中没有分配任何内存

int *x = malloc(sizeof(int));

关于风格
我更喜欢第一个,因为你没有释放指针占用的内存的机会较少。

答案 2 :(得分:2)

第一个是不正确的(除语法错误外) - 您正在将未初始化的指针传递给set_int()。正确的电话会是:

int main()
{
    int x;
    set_int(&x);
}

如果它们只是int,并且它不会失败,那么通常的答案就是“不” - 你通常会这样写:

int get_int(void)
{
    return 5;
}

int main()
{
    int x;
    x = get_int();
}

但是,如果它是一个更复杂的聚合类型,那么第二个版本很常见:

struct somestruct *new_somestruct(int p1, const char *p2)
{
    struct somestruct *s = malloc(sizeof *s);

    if (s)
    {
        s->x = 0;
        s->j = p1;
        s->abc = p2;
    }

    return s;
}

int main()
{
    struct somestruct *foo = new_somestruct(10, "Phil Collins");

    free(foo);

    return 0;
}

这允许struct somestruct *成为“不透明指针”,其中调用代码不知道类型struct somestruct的完整定义。标准库使用此约定 - 例如,FILE *

答案 3 :(得分:1)

绝对选择第一个版本。请注意,如果您忘记稍后释放该内存,则允许您省略动态内存分配(即SLOW),并且可能是错误的来源。

此外, if 由于某种原因决定使用第二种样式,请注意您不需要将指针初始化为NULL。任何malloc()返回都会覆盖此值。如果你内存不足,malloc()将自己返回NULL,没有你的帮助:-)。 所以int *temp = malloc(sizeof(int));就足够了。

答案 4 :(得分:1)

内存管理规则通常声明内存块的分配器也应该释放它。当返回分配的内存时,这是不可能的。因此,第二个应该更好。

对于像结构这样更复杂的类型,你通常会得到一个函数来初始化它,也许是一个处理它的函数。分配和解除分配应由您单独完成。

C使您可以自由地动态或静态地分配内存,并且只使用两种模式中的一种模式(如果您有一个返回动态分配的内存的函数就是这种情况)会限制您。

typedef struct
{
    int x;
    float y;
} foo;

void foo_init(foo* object, int x, float y)
{
    object->x = x;
    object->y = y;
}

int main()
{
    foo myFoo;
    foo_init(&foo, 1, 3.1416);
}

答案 5 :(得分:0)

在第二个中你需要一个指向它的指针才能工作,而在第一个中你没有使用返回值,尽管你应该这样做。

我倾向于选择第一个,在C中,但这取决于你实际在做什么,因为我怀疑你做的事情很简单。

保持您的代码尽可能简单,KISS原则仍然有效。

答案 6 :(得分:0)

如果某人不知道它是如何工作的,最好不要从函数返回一块已分配的内存,否则它们可能不会释放内存。 内存释放应该是分配内存的代码的责任。

答案 7 :(得分:0)

第一个是首选(假设简单的语法错误是固定的),因为它是你模拟Out参数的方式。但是,只有在调用者可以安排所有空间分配以在调用之前将值写入时,它才可用;当调用者缺少该信息时,你必须返回一个指向内存的指针(可能malloc,也许来自池等等。)

答案 8 :(得分:0)

您更普遍地问的是如何从函数返回值。这是一个很好的问题,因为它很难做对。您可以学到的是一些经验法则,可以阻止您制作可怕的代码。然后,阅读好的代码,直到内化不同的模式。

以下是我的建议:

  • 通常,任何返回 new 值的函数都应该通过其return语句执行此操作。这显然适用于结构,但也适用于数组,字符串和整数。由于整数是简单类型(它们适合一个机器字),你可以直接传递它们,而不是指针。

  • 永远不要将指针传递给整数,这是一种反模式。始终按值传递整数。

  • 学习按类型对功能进行分组,这样您就不必单独学习(或解释)每个案例。一个好的模型是一个简单的OO模型:一个_new函数,它创建一个不透明的结构并返回一个指向它的指针;一组函数,它们将指针指向该结构并用它做任务(设置属性,做功);一组返回该结构属性的函数;一个析构函数,它获取指向结构的指针并释放它。嘿presto,C变得更加漂亮。

  • 当你修改参数(只有结构或数组)时,坚持使用约定,例如stdc库总是从右到左复制;我解释的OO模型总是把结构指针放在第一位。

  • 避免在一个函数中修改多个参数。否则你会得到一些你不记得的复杂界面,最终你会出错。

  • 返回0表示成功,返回-1表示错误,当函数执行可能出错的情况时。在某些情况下,您可能必须返回-1表示错误,0或更高表示成功。

标准POSIX API是一个很好的模板,但不使用任何类型的模式。