c中malloc的多个单行赋值

Multiple one line assignments with malloc in c

假设下面的语句:

int *numbers, *inverse;
numbers = inverse = (int *)malloc(n * sizeof(int));

我很想知道这里发生了什么——我知道它是从右到左,所以首先要分配 inverse 的内存。然后我设置numbers等于inverse,那是否意味着numbers的内存位置将与inverse相同?或者它是否在 &numbers&inverse 位置分配了相同数量的内存?

例如,如果我做类似 inverse[i] = 5 的事情,那是否意味着 numbers[i] == 5

是的,您正在分配单个内存块。这就是指针的魔力!

第一项工作是删除多余的 (int*) 转换(如果类型不是内置的,这样的方案甚至可能有害)。这是C和C++的区别之一。

malloc(n * sizeof(int)); returns 类型的指针 void*.

该指针已分配给 inverse

但是 表达式 inverse = malloc(n * sizeof(int)) 的类型为 int*。因此,这可以有效地分配给 numbers.

非常清楚,malloc 只调用了一次,因此您应该只调用 free 一次。

你有:

int *numbers, *inverse;
numbers = inverse = (int *)malloc(n * sizeof(int));

这和写一样:

int *inverse = (int *)malloc(n * sizeof(int));
int *numbers = inverse;

变量numbers只是在inverse中有一个指针的副本——它指向同一个地方。但是,您可能要用一个指针遍历数组,同时从函数返回另一个指针,这可能是拥有两个副本的一个很好的理由。

只有一个内存分配;需要一次调用 free() 来释放分配的内存。传递给 free() 的值将与分配给 inversenumbers.

的原始值相同

你还问:

If I do something like inverse[i] = 5 will that mean that numbers[i] == 5?

如果您没有更改存储在 inversenumbers 中的值,并且如果 i0 范围内.. (n-1),则在赋值后,等式成立。指针是相同的(相同类型,相同值),因此对它们进行索引会产生相同的结果。当然也有inverse[i] == numbers[i]的意思。

只分配了一块内存,inversenumbers都指向同一个内存块。

我们可以通过实验验证这一点。

#include <assert>

int main() {
    int n = 100;
    int *numbers, *inverse;
    numbers = inverse = (int *)malloc(n * sizeof(int));

    numbers[0] = 10;
    inverse[0] = 20;

    // If numbers and inverse point to the same memory, then we would expect
    // that numbers[0] is now 20.
    assert(inverse[0] == 20);
    assert(numbers[0] == 20);
}

TL;DR,是的,inversenumbers 都指向相同的内存。


长答案: 为什么 部分,引用 C11,章节 §6.5.16,赋值运算符 (强调我的)

[...] An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion.

因此,正如您正确提到的那样,for right-to-left associativity of the assignment operator =,评估看起来像

numbers = ( inverse = (int *)malloc(n * sizeof(int)) );

所以,一旦 inverse = (int *)malloc(n * sizeof(int)) 被评估,

  • 这个表达式的值就是inverse赋值后的值
  • 此外,类型与inverse
  • 的类型相同

(且两者都有效) 因此,下一次评估与

相同
 numbers = inverse;

所以,(如果你想要),你可以像

这样分解语句
if ( (inverse = malloc(n * sizeof*inverse )) )  //error check, just saying
      numbers = inverse;

and finally, if you're wondering why I removed the cast, see this discussion for more info on this.

在 C 中,赋值 (=+=、...) 是一个运算符,如 +- 等。它产生值操作员的左侧。看标准 6.5.16p3 它们是右结合的,求值顺序是:

numbers = ( inverse = malloc(n * sizeof(int)) );

(通常不要将 malloc & friends 或 void * 的结果转换为指针。C 中不需要它并且可能有害。)

所以 number 得到与 inverse 相同的 malloc 为正确的分配返回的是什么。

强调:这与指针无关:

int i, k;
i = k = 4;

原理完全一样

编辑:

要明确说明(再一次):对于每个运算符,赋值的右侧被精确计算一次。您也不会期望 f(x) + g(x) + h(x) 会调用两次 h

对于指针:malloc returns一个指向内存块的指针,两个指针具有相同的值,因此它们指向同一个内存块。由于两者具有相同的类型,您可以使用两者来访问内存块。

在这里你分配了一个内存块并将地址存储在两个指针中。所以两个指针都指向同一个地址