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编译器)。
我在玩 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编译器)。