Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用函数返回值而不首先存储它-为什么很少看到这种情况?_C_Syntax_Return Value_Function Call - Fatal编程技术网

C 使用函数返回值而不首先存储它-为什么很少看到这种情况?

C 使用函数返回值而不首先存储它-为什么很少看到这种情况?,c,syntax,return-value,function-call,C,Syntax,Return Value,Function Call,直接使用函数的返回值而不首先将其存储在变量中(即foo()->bar,其中foo()返回一个指向具有成员bar的结构的指针,这似乎很少见。我尝试过的所有编译器似乎都允许这样做,但我很少在“野生”中看到它。除了您可能想先检查返回值,并假设您有一种适当的方式在以后释放内存之外,这在纯C中很少使用,还有什么原因吗 一个更明确的例子: #include <stdlib.h> #include <stdio.h> struct FooBar { int bar; } Fo

直接使用函数的返回值而不首先将其存储在变量中(即
foo()->bar
,其中
foo()
返回一个指向具有成员
bar
的结构的指针,这似乎很少见。我尝试过的所有编译器似乎都允许这样做,但我很少在“野生”中看到它。除了您可能想先检查返回值,并假设您有一种适当的方式在以后释放内存之外,这在纯C中很少使用,还有什么原因吗

一个更明确的例子:

#include <stdlib.h>
#include <stdio.h>

struct FooBar {
    int bar;
} FooBar;

struct FooBar *foo(void)
{
    struct FooBar *test = malloc(sizeof(*test));
    test->bar = 42;
    return test;
}    

int main (void)
{
    printf("%d\n", foo()->bar);
    return 1;
}
#包括
#包括
结构FooBar{
int-bar;
}福巴;
结构FooBar*foo(无效)
{
struct FooBar*test=malloc(sizeof(*test));
测试->棒=42;
回归试验;
}    
内部主(空)
{
printf(“%d\n”,foo()->bar);
返回1;
}
根据您的代码

 foo()->bar
可以,但不使用,因为在
foo()
返回空指针(可能表示某种失败)的情况下,您将调用

从相反的角度来看,如果使用的是直接解引用,那么函数不能返回任何无效指针。这会降低函数的健壮性和模块化程度

OTOH,如果将函数的返回值存储在变量中,则可以对变量执行空检查(携带
return
ed指针),然后进行解引用

要澄清一点,C标准中没有任何东西阻止您进行直接解引用,但是任何适当的编码准则都不允许(或者至少不鼓励)这样做

直接使用函数的返回值而不首先将其存储在变量中似乎不常见

没错,这反映了检查返回值的良好编程实践。许多函数通过使用特殊值(如
NULL
-1
EOF
)返回错误条件

未使用或未检查返回值的常见示例是输出函数

使用返回值但未检查的常见示例是
str…()
函数,其中返回值是输入的副本

return strcpy(dest, src);

使用好的代码,从函数中取消引用指针返回值而不保存指针意味着:

bar(foo()->field);
  • foo()
    的返回值不是
    NULL
  • 其他字段不感兴趣
  • 不需要对返回值进行内部管理,例如
    free()
    fclose()
  • 这组条件在用户代码中并不常见


    当函数返回指针时,最好的编码实践是在取消引用指针之前检查错误,因为
    NULL
    返回通常表示存在问题。如果函数可能已分配数据,则检查至关重要

    FILE *istream = fopen(filename, "r");
    if (istream == NULL) ...
    else { 
      foo(istream); 
      fclose(istream);
    }
    
    struct tm *tm = localtime(&t);
    if (tm ! NULL) {
      printf("Year %d\n", tm->tm_year + 1900);
    }
    
    当一个函数返回一个非指针时,需要的不是那么关键,但仍然是明智的

    int cnt = fscanf(istream, "%d", &value);
    if (cnt == 1) foo(value);
    
    有些函数很少检查其返回值

    printf("Hello World\n");  // return value not checked.
    

    您希望将返回值存储到单独变量中而不是直接使用它的主要原因有三个:

    • 它允许您在使用前对返回值执行完整性检查-
      NULL
      检查、范围检查(比如数组索引)、空字符串检查等。;
    • 它使调试更容易-您可以更容易地检查调试器中的返回值,并且可以更容易地记录这些值;此外,如果某个函数抛出segfault,您可以更容易地确定它是哪个函数;
    • 它使维护变得更容易——就像代码一样
      x = f(); 
      y = g(); 
      z = h(x, y);
      printf( "z = %d\n", z );
      比类似代码更容易理解和维护
       printf("z = %d\n", h(f(),g()));

    我相信人们可以想出其他的理由,但这是我的三大理由。

    好吧,这是一个在使用返回值之前需要检查返回值的情况。这是问题中的OP.QUOTE提到的。除了您可能想要检查返回值之外,有什么原因很少在纯C中使用它吗在使用它之前先使用值?@Haris和我回答了为什么部分:)
    sizeof(FooBar)
    -->
    sizeof(*test)
    内存泄漏。如果您不存储malloc()的返回值,您怎么能
    free()
    它呢?C不是自动垃圾收集的。要扩展@SouravGhosh的评论,
    sizeof(FooBar)
    在该上下文中是完全正确的,但是
    sizeof(*test)
    (或
    sizeof*test)
    更健壮。如果指针的类型发生变化,则
    sizeof(*test)
    保持正确。不将函数结果(以及其他内容)存储到中间/temp变量中的开发人员会不断在此处发布抱怨“修复我的代码,我找不到错误”。他们不够优秀,开发人员无法理解调试的简单性比节省一行代码要重要得多。