C指针(数组)内存分配(十六进制)

C pointers (arrays) memory allocation (hexadecimal)

我在玩 C 中的内存寻址,遇到了一个我无法完全解释的情况。

编辑:代码由 C++ 编译器编译。 (g++)

#include <cstdlib>
#include <cstdio>
int main()
{

    int* array[10]; //array of pointers to integers

    for(int i = 0; i < 10; i++)
        {
            array[i] = (int*)malloc(sizeof(int));
            *(array[i]) = i;
        }


    printf("\n");
    for(int i = 0; i < 10; i++)
       {
            printf("%d:%p\n", *(array[i]), array[i]);
       }
    printf("\n");




    int arr[10]; //array of integers

    int* start = arr; //pointer to the first element (array decay)
    for(int i = 0; i < 10; i++)
        arr[i] = i;

    printf("\n");
    for(int i = 0; i < 10; i++)
    {
        printf("%d:%p\n", *(start + i), start + i);
   }
   printf("\n");

 return 0;
 }

一切都可以编译并运行,但是我得到了奇怪的内存地址。 对于第一个数组,我得到类似的东西:

0:0x23e4010
1:0x23e4030 (32 bits between the addresses which is correct)

但是对于第二个数组我得到:

0:0x7ffdaf876290
1:0x7ffdaf876294 (only 4 bits? or maybe they are bytes - but why the long addresses???)

谁能解释一下? (还有没有一个函数可以毫不费力地将十六进制转换为十进制?)

首先,您的数组是一个指针数组。每个元素都是一个指针,当您为每个指向的指针分配内存时,它与您为该数组中的其他指针分配的内存完全无关。在这种情况下,它们实际上相隔 32 字节 ,但这纯属偶然。

在后一种情况下,您将在内存中创建一个整数数组,这些整数都聚集在一起,或 "contiguous"。它们将是相邻的,因此当您打印它们的地址时,您会看到这种模式,它们相隔 4 字节 。显然,int 在您的系统上是 4 个字节宽(这仍然很常见)。

"long addresses" 是由于您使用了动态分配:这将是您的系统恰好持有堆的虚拟内存区域。不用担心。

所以没有什么"strange"。

数组的 Int 使用 1 个字节。

让地址: - 数组[0]=5000

然后 - 阵列[1]=5001 - 阵列[2]=5002 - 数组[3]=5003 - 阵列[4]=5004 - 数组[5]=5005 - 数组[6]=5006 - 阵列[7]=5007 - 数组[8]=5008 - 数组[9]=5009

现在,您正在分配指针。 那么Pointer的地址:

  • *(数组[0])=5010
  • *(数组[1])=5011
  • *(数组[2])=5012
  • *(数组[3])=5013
  • *(数组[4])=5014
  • *(数组[5])=5015
  • *(数组[6])=5016
  • *(数组[7])=5017
  • *(数组[8])=5018
  • *(数组[9])=5019

在这里你可以很容易地看到array[i] 和*(array[i]) 之间的差异总是10bytes。 这是因为当调用任何数组时,只有它一次分配内存总大小。

现在第二个地址: 数组 arr 已定义但未被调用。 因此,在调用 arr 之前不会分配内存 这里调用是为了定义

现在,第一行说:

int arr[10];

那只定义了基址。 然后你把那个基地址给了 *start by:

int* start=arr;

因此指针得到了那个地址。 显然,令: 地址:

  • arr[0]=5020 那么:
  • *(开始+0)=5020

因为它是一个指针(不是数组)因此需要 4 个字节。 同样,所有地址范围将是:

  • arr[0]=5020 - 5023
  • arr[1]=5024- 5028 等等..

分配说明:

  • 每当我们定义一个数组时,它只定义基地址。 例如:

    int a[10];

将分配基地址,即起始地址,即a[0]的地址;

  • 无论何时定义一个指针,它也只会分配基地址。

  • 区别仅在于分配,即数组分配1byte,指针分配4byte(GCC/Linux/32bit编译器)。