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

问题描述 投票:0回答:6

以下两个代码块执行相同的操作:

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。

是否有理由使用其中任何一种,而不是风格偏好?我更喜欢将所有变量声明为指针,就像在第二个中一样,但我更频繁地看到第一个变量。

c pointers pass-by-reference
6个回答
2
投票

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

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

foo(num);

free(num);

要么:

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

要取消这一点的主要原因是第一种形式是最简单的。一个有效的指针变量必须指向程序控件中的内存,这需要比int *num; *num = 5;更多的工作


3
投票

不,这两个片段做的很不一样。第一个片段是格式良好的代码。由于取消引用未初始化的指针,第二个片段是Undefined Behavior。

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

警告:变量'num'在此处使用时未初始化[-Wuninitialized]


1
投票

以下两个代码块执行相同的操作:

不,他们没有。只有第一个完全定义了行为。第二个在执行*num = 5而没有指定有效指针指向num时取消引用一个野指针。

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

你似乎正在遭遇令人沮丧的共同点,它无法区分指针和它所指向的东西。它们是不同的,大部分是正交的声明int *num并未声明或保留任何空间用于int。它声明了一个可以指向int的指针,但是在指定一个指向int的指针之前,该指针的值无效。

是否有理由使用其中任何一种,而不是风格偏好?

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

我更喜欢将所有变量声明为指针,就像在第二个中一样,但我更频繁地看到第一个变量。

听到你看到第二个,我很遗憾。


0
投票

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

对于约翰库格曼的例子

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

在第一个例子中似乎没有任何优势。因此,如果你修复了第二个例子,你可能只需要更多的代码,而不需要任何额外的清晰度。

最后,我认为作为一个公平的整体总结,第二个例子实际上并没有获得“将所有变量声明为指针”的价值。你必须在某处拥有实际的记忆,而第一个例子就是明确的。它作为指针传递,因此除了声明内存的代码之外,它是一个指针。


0
投票

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]);
}

0
投票

我更喜欢将所有变量声明为指针,就像在第二个中一样,但我更频繁地看到第一个变量。

这句话没有多大意义 - 肯定不是你使用的所有东西都是指针。

代码

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

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

仅仅因为函数将指针作为参数并不意味着您必须将指针对象作为该参数传递。是的,你可以写类似的东西

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

但这并没有给你带来任何简单的写作

int num = 5;
foo( &num );

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

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

它们也可以用来构建动态数据结构,如列表,队列,树等等。但是你不应该将它们用于所有事情。

© www.soinside.com 2019 - 2024. All rights reserved.