在C中使用calloc时,什么存储在指针的地址?

时间:2011-12-08 19:06:54

标签: c pointers

我很难理解这个程序来说明指针(来自http://theocacao.com/document.page/234):

下面我不明白为什么:

int * currentSlot = memoryBlock

未使用&memoryBlock。我看了评论,但没有得到它。什么是memoryBlock放在那里& memoryBlock不会?是不是都会将指针返回到使用calloc创建的一组int(假设我理解已经完成了什么)? * memoryBlock之后calloc的真实情况是什么?

然后在这里,*currentSlot = rand();,解除引用如何在这里工作?我认为取消引用会阻止* currentSlot将内存地址(引用)的值赋给实际值(不再是引用而是值)。

#include <stdio.h>
#include <stdlib.h> // for calloc and free
#include <time.h>   // for random seeding

main ()
{
  const int count = 10; 
  int * memoryBlock = calloc ( count, sizeof(int) );

  if ( memoryBlock == NULL )
  {
    // we can't assume the memoryBlock pointer is valid.
    // if it's NULL, something's wrong and we just exit
    return 1;
  }

  // currentSlot will hold the current "slot" in the,
  // array allowing us to move forward without losing
  // track of the beginning. Yes, C arrays are primitive
  //
  // Note we don't have to do '&memoryBlock' because
  // we don't want a pointer to a pointer. All we
  // want is a _copy_ of the same memory address

  int * currentSlot = memoryBlock;


  // seed random number so we can generate values
  srand(time(NULL));

  int i;    
  for ( i = 0; i < count; i++ )
  {
    // use the star to set the value at the slot,
    // then advance the pointer to the next slot    
    *currentSlot = rand();
    currentSlot++; 
  }

  // reset the pointer back to the beginning of the
  // memory block (slot 0)
  currentSlot = memoryBlock;

  for ( i = 0; i < count; i++ )
  {
    // use the star to get the value at this slot,
    // then advance the pointer
    printf("Value at slot %i: %i\n", i, *currentSlot);
    currentSlot++;
  }

  // we're all done with this memory block so we
  // can free it  
  free( memoryBlock );
}

感谢您的帮助。

6 个答案:

答案 0 :(得分:3)

  

下面我不明白为什么:

int * currentSlot = memoryBlock
     

未使用&memoryBlock

因为memoryBlockcurrentSlot都是指向int的指针。 &memoryBlock将是指向int的指针的地址,即int **

什么是“in”memoryBlock是指向内存块的指针。

  

然后在这里,*currentSlot = rand();,解除引用如何在这里工作?

这是C的规则:当这样的解除引用表达式出现在表达式的左侧时,右侧的值存储在被解除引用的指针指向的内存位置。

答案 1 :(得分:1)

memoryBlock是一个整数数组(int*)。 (从技术上讲,这是一个指向int的指针,但由于它被分配了足够的空间用于10个整数,你可以将它视为数组的开头)

*memoryBlock是memoryBlock指向的整数(数组中的第一个int)。虽然符号看起来与声明相同,但它实际上是取消引用该值。恕我直言,它写得不好,因为它应该被宣布

int* currentSlot = memoryBlock;

更清楚地表明它是一个指向整数的指针,但这是一种风格选择。

&memoryBlock指针的地址。

int * currentSlot = memoryBlock;

将指针存储到currentSlot中的第一个插槽。然后程序生成随机数,并通过递增currentSlot将其放入10个clost的每一个中(currentSlot内部将指针递增一个整数的长度。

希望有所帮助。

答案 2 :(得分:1)

int * memoryBlock;

memoryBlock是一个变量,它可以保存整数存储块的地址。 memoryBlock变量的大小是地址的大小。通常为4或8个字节(sizeof(int *))。它的类型是“指向int的指针”。

memoryBlock = calloc ( 5, sizeof(int) );

为memoryBlock变量分配了能够容纳5个整数的内存块的起始地址。内存块大小为5 * sizeof(int)bytes。

memoryBlock + 1是块中第二个整数的地址。 memoryBlock + 5是一个传递了块中最后一个整数的地址。

* memoryBlock是地址的内容(第一个整数)。 type是整数。

*(memmoryBlock + 0) = 0;
*(memmoryBlock + 1) = 1;
*(memmoryBlock + 2) = 2;
*(memmoryBlock + 3) = 3;
*(memmoryBlock + 4) = 4;
//    *(memmoryBlock + 5) = 5; illegal

将整数分配给内存块。 与上述相同的订单形式。

memmoryBlock[0] = 0;
memmoryBlock[1] = 1;
memmoryBlock[2] = 2;
memmoryBlock[3] = 3;
memmoryBlock[4] = 4;
//    memmoryBlock[5] = 5; illegal

&amp; memoryBlock是memoryBlock变量的地址。这不是callocated空间的地址。它的类型是int **“指向整数指针的指针”而不是int *。

int ** pmemoryBlock;

pmemoryBlock是一个变量,它保存整数存储块的地址。 pmemoryBlock的大小是地址的大小。通常为4或8个字节(sizeof(int **))。

pmemoryBlock = &memoryBlock;

pmemoryBlock被赋予一个变量的地址,该变量保存能够容纳5个整数的内存块的起始地址。

* pmemoryBlock是内存块的地址。 ** pmemoryBlock是内存块中的第一个整数 *((* pmemoryBlock)+ 0)是内存块中的第一个整数 *((* pmemoryBlock)+ 1)是内存块中的秒整数

...

答案 3 :(得分:0)

在代码中,memoryBlock是一些存储整数的内存的指针。也就是说,变量memoryBlock的实际值是刚刚分配的地址。如果您使用&memoryBlock,则会获得存储变量的地址,而不是它所指向的地址。

让我们举一个例子:

int foo = 5;
/* the variable "foo" is stored in memory,
   and that memory contains the number 5 */

int bar = 7;
/* the variable "foo" is stored in memory,
   and that memory contains the number 7 */

int *foo_pointer = &foo;
/* the variable "foo_pointer" is stored in memory,
   and that memory contains the address of the variable "foo" */

foo_pointer = &bar;
/* the contents of the variable "foo_pointer" is no longer the address
   of where the variable "foo" is in memory, instead it is the address
   of where the variable "bar" */

我希望这是有道理的,而且它有点帮助。

答案 4 :(得分:0)

使用&amp; memoryBlock并不是假设,这是指向要清除的内存的指针的(int **(heh!))地址。换句话说,memoryBLock(如果它不是NULL)指向calloc()'ed内存中的第一个int(即,保存地址)。要引用清除为0的内存,请使用* memoryBlock。

如果您发现自己试图使用&amp; memoryBlock,请不要:在您发布的代码片段中,这绝不是正确的做法。

HTH。如果没有帮助,请返回K&amp; R并再学习指针。也许更多。

答案 5 :(得分:0)

int *是一个指针,可以解除引用。 int **是指针的指针,可以解除引用两次。那么这是什么意思?好吧,指针只不过是一个整数。内存地址从零开始到最大范围。对于32位系统,其可寻址存储器范围为0到2 ^ 32-1(或4294967295)。每个地址都有一个字节值。如果你有一个int *,那么它将一次访问4字节的地址。 此外,为简单起见,我们假设这是一个虚拟地址,您不能只访问所有这些内存,一些将受到保护(系统),一些无效(未提交)。要获得更多内存,您可以要求系统从此范围分配更多内存。 Linux中的sbrk,Windows中的VirtualAlloc,但您通常会通过C&C的malloc或calloc访问它们。

让我们说,你从0x100开始: 0x100:&#39; h&#39;,&#39;&#39; l&#39;,&#39; l&#39;,&#39; o&#39;,&#39 ; \ 0&#39;

所以这个字符串占用内存从0x100到0x105(包括空终止符)。如果你有一个指针:

char * p = 0x100;

然后你有:

p      // 0x100
*p     // 'h'
p+1    // 0x101
*(p+1) // 'e'
p += 2 // 0x102
*p     // 'l'
p = 0x200;
p      // now points to 0x200 in memory
*p     // contains whatever value is in 0x200

如果你有int指针,那么你一次访问4字节的内存(或者你的系统上有一个很大的int)。

所以在所有背景下,当你运行calloc时,它会返回你所要求的块的地址。

int *memoryBlock = calloc(count, sizeof(int));
// memoryBlock is an array of int, assuming sizeof(int) == 4, then
// you have 40 bytes of memory starting from the address of what is
// returned by calloc.

memoryBlock++;     // now memoryBlock is at base address + 4
*memoryBlock = 10; // now that address contains the value 10
(*memoryBlock)++;  // now that address contains the value 11
memoryBlock++;     // now memoryBlock is 4 bytes further