简体   繁体   English

在c中使用malloc进行多个单行分配

[英]Multiple one line assignments with malloc in c

Suppose the below statement: 假设以下语句:

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

I am curious to know what is going on here - I know it is right to left, so first the memory for inverse is being allocated. 我很好奇这是怎么回事-我知道它是从右到左,所以首先要分配用于inverse的内存。 Then I set numbers equal to inverse , will that mean that the memory location of numbers will be the same as inverse ? 然后我将numbers设置为inverse ,这是否意味着numbers的存储位置将与inverse numbers相同? Or does it allocate the same amount of memory at locations &numbers and &inverse ? 还是在位置&numbers&inverse分配相同数量的内存?

For example, if I do something like inverse[i] = 5 will that mean that numbers[i] == 5 ? 例如,如果我做类似inverse[i] = 5事情,那意味着numbers[i] == 5

You have: 你有:

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

That's the same as writing: 这与写作相同:

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

The variable numbers simply has a copy of the pointer that is in inverse — it points to the same place. 变量numbers只是具有inverse的指针副本-它指向同一位置。 However, you might be about to iterate through the array with one pointer while returning the other from the function, which could be a good reason for having the two copies. 但是,您可能要使用一个指针遍历数组,同时从函数返回另一个指针,这可能是拥有两个副本的一个很好的理由。

There's a single memory allocation; 只有一个内存分配; there will need to be a single call to free() to release the allocated memory. 只需调用一次free()即可释放分配的内存。 The value passed to free() will be the same as the original value assigned to either inverse or numbers . 传递给free()的值将与分配给inversenumbers的原始值相同。

You also ask: 您还问:

If I do something like inverse[i] = 5 will that mean that numbers[i] == 5 ? 如果我做类似inverse[i] = 5事情,那将意味着numbers[i] == 5

If you've not changed the value stored in either inverse or numbers , and if i is in the range 0 .. (n-1) , then after the assignment, the equality will hold. 如果您尚未更改存储在inversenumbers ,并且i处于0 .. (n-1)范围内,则赋值后将保持相等。 The pointers are the same (same type, same value), so indexing them produces the same result. 指针是相同的(相同的类型,相同的值),因此对它们进行索引将产生相同的结果。 It also means inverse[i] == numbers[i] of course. 当然,这也意味着inverse[i] == numbers[i]

The first job is to drop the (int*) cast which is superfluous (and such a scheme can even be harmful if the type is not built-in). 第一项工作是删除多余的(int*)强制类型转换(如果类型不是内置的,则这种方案甚至可能有害)。 This is one of the differences between C and C++. 这是C和C ++之间的区别之一。

malloc(n * sizeof(int)); returns a pointer of type void* . 返回类型为void*的指针。

That pointer is assigned to inverse . 该指针被分配给inverse

But the expression inverse = malloc(n * sizeof(int)) has type int* . 但是表达式 inverse = malloc(n * sizeof(int))类型为int* This therefore can then be validly assigned to numbers . 因此,可以将其有效地分配给numbers

To be very clear, malloc is called exactly once, and therefore you should call free exactly once. 十分清楚, malloc仅被调用一次,因此,您应该只对free调用一次。

TL;DR, yes, both inverse and numbers point to same memory. TL; DR,是的, inverse numbersnumbers指向相同的内存。


Long answer: On why part, quoting C11 , chapter §6.5.16, Assignment operators (emphasis mine) 长答案: 为什么在引用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 . 赋值表达式的类型是左值转换后左操作数将具有类型

So, as you have mentioned correctly, for right-to-left associativity of the assignment operator = , the evaluation looks like 因此,正如您已经正确提到的那样, 对于赋值运算符=从右到左的关联 ,求值看起来像

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

so, once inverse = (int *)malloc(n * sizeof(int)) is evaluated, 因此,一旦求inverse = (int *)malloc(n * sizeof(int))

  • The value of this expression is the value of inverse after the assignment 该表达式的值是赋值后的inverse
  • Also, the type is as of the same type of inverse 同样,类型与inverse类型相同

( and both are valid ) thus, the next evaluation is the same as 并且都有效 ),因此,下一次评估与

 numbers = inverse;

So, ( if you want ), you can break down the statements like 因此,( 如果需要 ),您可以细分如下语句

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. 最后,如果您想知道为什么我删除了演员表,请参阅此讨论以获取更多信息。

Only one chunk of memory has been allocated, and both inverse and numbers point to the same chunk. 仅分配了一块内存,并且inverse numbersnumbers指向同一块。

We can verify this experimentally. 我们可以通过实验来验证。

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

Yes, you are allocating a single block of memory. 是的,您正在分配一个内存块。 That's the magic of pointers! 这就是指针的魔力!

Here you are allocating a single block of memory And storing the address in two pointers. 在这里,您将分配一个内存块,并将地址存储在两个指针中。 So both the pointers will point to the same address 所以两个指针将指向相同的地址

In C, an assignment ( = , += , ...) is an operator like + , - , etc. It yields the value of the left hand side of the operator. 在C语言中,赋值( =+= ,...)是+-等运算符。它产生该运算符左手边的值。 See the standard 6.5.16p3 They are right associative, evaluation order is: 参见标准6.5.16p3,它们是正确的关联,评估顺序为:

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

(Don't cast the result of malloc & friends or void * in general to pointers. It is not required in C and potentially harmful.) (一般不要将malloc和friends的结果malloc为指针,也不要将void *强制转换为指针。C语言中不需要它,这可能有害。)

So number gets the same value as inverse . 因此number获得与inverse相同的 Which is whatever the malloc returned for the right assignment. 这是malloc为正确分配返回的结果。

To emphasise: this is no way related to pointers: 要强调的是:这与指针无关:

int i, k;
i = k = 4;

is exactly the same principle. 原理是完全一样的。

Edit: 编辑:

To state it clear (once more): The right hand side of an assignment as for every operator is evaluated exactly once . 明确说明(一次以上): 对于每个运算符 ,赋值的右侧仅被评估一次 You would not expect f(x) + g(x) + h(x) to have h called twice either. 您不会期望f(x) + g(x) + h(x)也不会调用h两次。

For the pointers: malloc returns a pointer to a memory block, both pointers have the same value, thus they point to the same memory block. 对于指针: malloc返回指向内存块的指针,这两个指针具有相同的值,因此它们指向同一内存块。 As both have the same type, you may use both to access the memory block. 由于两者具有相同的类型,因此您可以使用两者来访问存储块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM