使用函数自增

Incrementation using functions

我想使用 C 中的函数 增加整数的值。

所以首先我写了一个函数 inc,其中我递增了整数 v 的值。然后在 main 函数中我声明了一个新变量 a 并使用 inc(a) 函数递增。

这是我的代码:

#include<stdio.h>
void inc(int v)
{
    v++;
}
int main()
{
    int a;
    scanf("%d",&a);
    inc(a);
    printf("%d",a);
    return 0;
}

但输出与输入值相同。它不是递增的。

即如果我将输入作为 45,我期望值 46 作为输出。但输出仍然是 45。我哪里出错了?有人请解释一下。

所以我做了一些研究,发现使用指针时会出现预期的答案,这是它的代码

#include<stdio.h>
void inc(int *v) {
    (*v)++;
}

int main() {
    int a;
    scanf("%d", &a);
    inc(&a);
    printf("%d", a);
    return 0;
}  

为什么没有指针的方法不正确?

同样在第二种方法中,为什么我们将参数作为地址传递,即 &a。为什么我们不能将其作为 a 传递?

本人是C新手,有疑惑请大神指教

您始终将变量、值或引用的副本传递给函数。因此,发送值的副本不会影响 main 函数。但是,发送其引用的副本将影响 main 函数,因为您说了您的变量在内存中的位置。

Also in the second method why are we passing the argument as address i.e &a. Why can't we pass it as a?

你这里是用指针来操作,当你把地址的值改成那个指针的时候,原来的值也跟着变了。

另一方面,当您按值传递变量 a 时,它只会制作一个副本并在函数调用中递增它,原始值不会发生任何变化。第一种方法不行,因为函数传入的变量是传值类型

编辑: 这个问题现在只在 C 中标记了。但是对于额外的信息,在 C++ 中有一种不需要指针的方法,它叫做 pass-by-reference (使用变量的原始副本进行操作)可以用函数签名上的符号表示,例如:

void changeRealValue(int& value) {
// _____________________^________
    value++; // original value is incremented now
}

Pointer 是一个包含对象地址的变量。指针不携带有关对象内容的信息,但包含有关对象所在位置的信息。

指针在 C 编程中被广泛使用。 在处理数组时经常使用指针。

计算机内存可以被认为是一系列编号的单字节单元格,可以单独或按块访问。

内存中的每个变量都有自己的地址——它所在的第一个单元格的编号,以及它的值。指针也是在内存中分配的变量。它也有一个地址,它的值是某个其他变量的地址。声明为指针的变量在 RAM 中占用 4 个字节(在 32 位版本的编译器的情况下)。

指针和任何变量一样,必须声明

сhar c;   // variable
char *p; // pointer
p = &c;  // p = address of c

看这个例子:

#include <stdio.h>
#include <stdlib.h>
int main()
{
  int a, *b;
  system("chcp 1251");
  system("cls");
  a = 134;
  b = &a;
  // %x = display the number in hexadecimal form
  printf("\n The value of the variable a is %d = %x hex.", a,a);
  printf("\n The address of the variable a is %x hex.", &a);
  printf("\n Data at pointer address b are equal %d = %x hex.", *b,*b);
  printf("\n The value of b pointer is %x hex.", b);
  printf("\n Location address of pointer b is %x hex.", &b);
  getchar();
  return 0;
}

问题是默认情况下 c 对函数使用按值传递。这意味着如果您在主函数中按以下方式调用函数,

int a = 45;
inc(a);

函数只知道值 45 而不知道变量 a。因此,它将创建一个新的局部变量(在您的情况下为 int v),该变量存储值 45 并递增。由于该函数不知道关于 a 的任何信息,特别是不知道 a 在内存中的位置,因此无法修改它。一般有两种方法可以解决:

  1. 使用 returns:

在这种情况下,该函数会继续使用传递的参数值操作本地副本。最终它可以return 得到想要的函数输出。这将通过以下方式实现:

#include<stdio.h>
void inc(int v)
{
    v++;
    return v
}

int main()
{
    int a;
    scanf("%d",&a);
    a = inc(a);
    printf("%d",a);
    return 0;
}
  1. 将参数作为指针传递:

在第二种情况下,您已经找到了,您通过引用传递了您的论点。这样函数就知道了 a 的内存地址,因此可以直接操作存储在 a 中的值。函数定义 void inc(int *v) 中 v 旁边的小星形图标定义函数将地址作为输入。因此,您必须像您发布的代码中那样使用 &a 传递 a 的地址。

总结:

您的功能,或您以后实现的任何功能,可以根据您的需要选择上述两种类型之一。但是,作为准则,它应该永远不要同时操纵传递地址和 return 处的值。这可能会导致混乱,并导致代码通常可读性较差。

"Why is the method without pointers not correct?"

如果你使用指针参数,你的意图是指向调用者中的一个对象。然后,您可以在被调用的函数中修改此对象。这就是所谓的pass by reference。您在调用者中传递了一个对象的引用。

如果不使用指针,只是将变量的值by value传给函数,也就是把参数的值赋值给一个函数-局部变量。在函数内部,您只能修改此函数局部变量的值,而不能修改调用者中的对象。

What's the difference between passing by reference vs. passing by value?

Also in the second method why are we passing the argument as address i.e &a. Why can't we pass it as a?"

在这种情况下,& 运算符获得 a 的地址,需要将其分配给指针参数。

指针总是存储要指向的对象的地址,而不是指向对象的值。

没有地址,指针不表示对象。


请学习更多关于指针的知识并阅读一本很好的 C 入门书籍,例如 Modern C(您可以在那里免费获得它)。

您还可以在这里找到此内容和其他内容:

The Definitive C Book Guide and List

一般在函数和参数传递的前几章有说明。

简答:

C 是默认值传递。如果未指定指针,inc 中的 v 只是 main 中具有相同值的 a 的副本。

也就是说,v++ 会在 inc 的范围内增加 v,但不会影响其他人。

对于指针,(*v)++表示“在v指向的地方加一个值”

如果您使用的是 C++,则通过引用传递是另一种解决方案。