【问题标题】:Return Value or Passing Pointer as Argument?返回值或传递指针作为参数?
【发布时间】:2021-07-02 00:58:43
【问题描述】:

我了解到,为了通过调用函数来访问或修改变量的值,我们需要将指针作为参数传递,如下所示:

#include <stdio.h>

//create a function 
void Increment(int* x) {    
   *x = *x+1;
   printf("Address of variable x in increment = %p\n",x); 

}

int main() {
   int a;
   a = 10;
   Increment(&a);   
   printf("Address of variable 'a' in main = %p\n",&a);
   printf("Value of a in main function = %d\n",a); 


}

但是我又做了一个测试,发现通过调用函数并返回值,也可以达到同样的效果。

#include <stdio.h>

//create a function 
int Increment(int x) {        // do not use VOID
   x = x+1;
   printf("Address of variable x in increment = %p\n",x); 
   return x;                  

}

int main() {
   int a;
   a = 10;
       int hasil;
       hasil = Increment(a);   
   printf("Address of variable 'a' in main = %p\n",&a);
   printf("Value of a in main function = %d\n",hasil); 


}

我的问题:

1) 如果我可以使用返回值来获得相同的结果,我是否必须将指针作为参数传递?

2) 我观察到当我从返回值的函数中打印变量“x”的内存地址时,内存地址非常短 0xb ,知道为什么吗?通常地址很长。

【问题讨论】:

  • 如果要修改多个变量怎么办? (他们也不做完全相同的事情——第二个版本复制了变量的值)
  • 返回函数结果表示可以在表达式中使用; void 函数不能在表达式中使用。

标签: c


【解决方案1】:

1) 如果我可以使用返回值来获得相同的结果,我是否必须将指针作为参数传递?

不,您不必总是这样做。但是观察到它释放了函数的返回值以进行错误报告。一个很简单的例子:

enum error_code {
  E_SUCCESS,
  E_GENERAL_FAILURE,
  E_MEMORY_ALLOCATION_FAILED,
  E_INVALID_ARGUMENT,
  E_FILE_NOT_EXIST
};

struct my_important_data {
  // stuff
};

enum error_code fill_important_data_from_file(char const *file_name,
                                              struct my_important_data **data)
{
  if(!data || !file_name)
    return E_INVALID_ARGUMENT;

  *data = malloc(sizeof(**data));

  if(!*data)
    return E_MEMORY_ALLOCATION_FAILED;

  // Return different error codes based on type of failure
  // so the caller can know what exactly went wrong

  return E_SUCCESS;
}

2) 我观察到当我从返回值的函数中打印变量“x”的内存地址时,内存地址非常短 0xb ,知道为什么吗?通常地址很长。

那是因为您使用 %p 转换说明符来打印常规 int,而不是实际地址。严格来说,这会导致 printf 函数具有未定义的行为。

【讨论】:

  • 您能否进一步解释一下“释放函数的返回值以进行错误报告”是什么意思?至于%p,我应该用什么来打印实际地址?
  • @LionGordon 在 C 语言中,返回值通常用于状态/错误代码,因为没有异常。因此,这取决于您的 API 设计,以及您希望如何处理返回值。
  • @LionGordon - 您可以通过获取地址(void*)&amp;x 来打印x 的地址。举个例子,看我修改过的帖子。
  • @StoryTeller 好的,我现在记得 void*
  • @LionGordon - 单独的void* 是不够的,你必须使用地址运算符&amp;
【解决方案2】:

当你需要修改数组的元素时,你需要传递一个指向函数的指针。在 C 中,您不能传递数组或从函数返回数组。

第二个问题的答案是,在 C 函数中,参数是按值传递的。这意味着传递参数的值被复制到函数的参数(函数的本地)。因此传递参数的地址和函数参数的地址是不同的。

【讨论】:

  • 不要修改数组的元素,因为数组是通过引用传递的。
  • @PaulOgilvie; C 仅支持按值传递。没有通过引用。
  • 是的,Hacks,这意味着编译器“按值”传递数组的地址,因此,数组是“按引用传递”的。您需要传递一个指向数组的指针,例如int *A; ... f(&amp;A){*A=realloc(..
  • @LionGordon;不。它是指针传递,最终是引用传递。
  • @hacks 我没有给你投反对票,我不知道是谁干的:D
【解决方案3】:

如果参数x 是通过点或引用传递的,则不会创建x 的值副本。 如果没有,则创建一个副本。这就是区别。
想想这种情况,如果参数是复杂的struct test,复制test是浪费时间。
如果你通过点x,你可以将它作为输入也可以作为输出。

【讨论】:

  • 请让您的解决方案更清晰;按原样理解有点困难。
  • @Charles 我明白这一点,但我想问如果我可以通过使用返回值来获得相同的结果,为什么我应该使用指针
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
相关资源
最近更新 更多