将所有变量声明为指针与在 C 中使用地址运算符

Declaring all variables as pointers vs. using address operators in C

下面两段代码做同样的事情:

void foo(int *num) {...}

int main(void)
{
    int num = 5;
    foo(&num);

    ...
}
void foo(int *num) {...}

int main(void)
{
    int *num;
    *num = 5;
    foo(num);

    ...
}

在这两种情况下,foo 都需要一个指向 int 的指针参数。首先,我声明了一个 int 并使用地址运算符 (&) 将其传递给 foo。在第二个中我声明了一个指针变量并直接将它传递给 foo.

除了风格偏好之外,是否有使用其中任何一个的理由?我更喜欢将所有变量声明为指针,如第二个,但我更频繁地看到第一个。

不,这两个片段的作用截然不同。第一个片段是格式正确的代码。第二个片段是由于取消引用未初始化的指针而导致的未定义行为。

第二个版本在执行时可能会崩溃或做一些其他不需要的事情。此外,在任何现代编译器上编译时都带有警告,它会显示警告,例如:

warning: variable 'num' is uninitialized when used here [-Wuninitialized]

The following two blocks of code do the same thing:

不,他们没有。只有第一个完全定义了行为。第二个在没有为 num.

分配有效指针的情况下执行 *num = 5 时取消引用野指针

In both cases foo expects a pointer-to-int argument. In the first I declare an int and use the address operator (&) to pass it into foo. In the second I declare a pointer variable and directly pass it into foo.

您似乎正在为无法区分指针和它所指向的对象这一令人苦恼的常见问题而苦恼。它们是不同的并且在很大程度上是正交的。声明 int *num 不会为 int 声明或保留任何 space。它声明了一个 可以 指向 int 的指针,但是该指针的值无效,直到您分配一个 确实 指向int.

Is there a reason to use either one, other than a stylistic preference?

是的。第一个有效,第二个无效。

I prefer to declare all of my variables as pointers, as in the second, but I see the first a lot more frequently.

得知您看到第二个 ,我感到很遗憾

虽然第一个代码片段获取变量的地址并将其传递给 foo,但第二个代码片段取消引用未初始化的指针。你本可以做的是:

int *num = malloc(sizeof(int));
*num = 5;

foo(num);

free(num);

或者:

int num = 5;
int *p = #
foo(p);

最主要的是第一种形式是最简单的。一个有效的指针变量必须指向程序控制范围内的内存,这需要比 int *num; *num = 5;

更多的工作

当然,正如其他人所指出的,第二个你需要将点初始化为有效分配的内存。所以这是支持第一个代码的一点。

以 John Kugelman 为例

int num;
int *p = #
*p = 5;
foo(p);

与第一个示例相比似乎没有任何优势。因此,如果您修复第二个示例,您可能只会得到更多的代码,而没有任何额外的清晰度。

最后,我认为作为一个公平的整体总结,第二个例子确实没有得到 "declare all of my variables as pointers" 的值。您必须在某处有实际内存,第一个示例清楚地说明了这一点。它作为指针传递,因此除了声明内存的代码外,它是一个指针。

一个

void one(void) {
    int n = 42; // initialization
    foo(&n);
    putchar(n);
}

两个

void two(void) {
    int *n;
    n = malloc(sizeof *n);
    *n = 42; // no initialization
    foo(n);
    putchar(*n);
    free(n);
}

三个

void three(void) {
    int n[1] = { 42 }; // initialization
    foo(n);
    putchar(*n); //putchar(n[0]);
}

I prefer to declare all of my variables as pointers, as in the second, but I see the first a lot more frequently.

这种说法没有多大意义 - 当然不是 您使用的所有东西 都是指针。

密码

int *num;
*num = 5;
foo( num );

格式不正确,因为 num 没有指向任何东西(它的值是 indeterminate)。您正在尝试将 5 分配给某个随机内存地址,这可能会导致段错误或损坏其他数据。它可能 没有明显问题地按预期工作,但这是偶然的,并非设计。

仅仅因为一个函数接受一个指针作为参数并不意味着你必须传递一个指针对象作为那个参数。是的,你可以写出类似

的东西
int num;
int *numptr = #
*numptr = 5;
foo( numptr )

但这并不能给你带来任何简单的写作

int num = 5;
foo( &num );

C 要求我们在2种情况下使用指针:

  • 当函数需要更新其输入参数之一时;
  • 当我们需要跟踪动态分配的内存时;

它们还可用于构建动态数据结构,如列表、队列、树等。但是您不应该将它们用于所有