变量分配的字节在内存中是连续的吗?
Are the bytes allocated by variables consecutive in memory?
初学C,正在研究指针。所以我的问题是“变量分配的字节在内存中是连续的吗?”是因为我认为通过从整数指针 (char *p_c = p_i - (sizeof(char)))
创建一个 char 指针,char 指针将精确指向整数的第二个字节。
例如:
整型变量占用 4 个字节,字符变量占用 1 个字节。
#include <stdio.h>
int main(){
int a = 4276545;
int *p = &a;
char *p_c1 = p - (1*sizeof(char));
printf("Value of p_c1 (second byte of a) is %c\n", *p_c1);
}
二进制的 ASCII 'A' 字符是 01000001。
4276545十进制转二进制为00000000 01000001 01000001 01000001.
p_c1不是指向00000000 01000001 01000001 01000001吗?
正在打印 *p_c1,我原以为它是 'A',但它打印了 'P'。
而且它不是因为它是一个随机字符,它总是在每次执行时发生变化,它总是打印 'P'。为什么?
sizeof(char)
保证为1(不管多少位),所以你有char *p_c1 = p - 1;
问题 1:
当您对指针进行加法或减法时,您将地址更改 sizeof(*p)
,因此您不是将地址更改一个字节,而是更改 sizeof(int)
个字节。这是必要的,因为 a[i] == *(a+i)
等效。
问题 2:
你在应该加的时候减了。某物的地址是它开始的地址,所以减去会导致在 a
之外的位置。你想搬进 a
,所以你想添加。
固定:
int a = 0x41424344;
char *p = (char *)&a;
for ( size_t i=0; i<sizeof(int); ++i )
printf( "%zu %d %c\n", i, *(p+i), *(p+i) );
输出因系统而异,但您应该在 little-endian 系统上获得以下内容,其中 char
类型大小为 8 位,int
类型大小为 32 位尺寸:
0 68 D
1 67 C
2 66 B
3 65 A
An integer variable takes 4 bytes
这是一个错误的说法。正确的说法是,如果 CHAR_BIT=8
,整数需要 至少 2 个字节,如果 CHAR_BIT>=16
,则 至少需要 1 个字节。有些系统 CHAR_BIT 是 64,在这样的系统上所有类型都是 sizeof(TYPE) = 1
。这个想法是,int 的大小必须至少为 16 位。有些系统需要进行几次提取才能将整数放入寄存器。
char *p_c1 = p - (1*sizeof(char));
你可以把整型变量int a
想象成一个长度为1的数组,如果取整型的地址,就相当于取数组第一个元素的地址。
你尝试做的是在 a
地址之前取前一个整数(因为 (1 times sizeof(char) )= 1
)并考虑那个的第一个字节整数。这是不正确的,访问超出其限制的数组或访问未明确分配给变量的地址是未定义的行为。
正如@ikegami 所说“当你对一个指针进行加法或减法时,你通过 sizeof(*p) 改变了地址”,所以通过类型转换和加 1,我能够访问 a 的第二个字节,现在正在打印 'A'
#include <stdio.h>
int main(){
int a = 4276545;
int *p = &a;
char *p_c1 = (char*) p + 1;
printf("Value of p_c1 (second byte of a) is %c\n", *p_c1);
}
谢谢大家的评论,学到了很多
初学C,正在研究指针。所以我的问题是“变量分配的字节在内存中是连续的吗?”是因为我认为通过从整数指针 (char *p_c = p_i - (sizeof(char)))
创建一个 char 指针,char 指针将精确指向整数的第二个字节。
例如: 整型变量占用 4 个字节,字符变量占用 1 个字节。
#include <stdio.h>
int main(){
int a = 4276545;
int *p = &a;
char *p_c1 = p - (1*sizeof(char));
printf("Value of p_c1 (second byte of a) is %c\n", *p_c1);
}
二进制的 ASCII 'A' 字符是 01000001。 4276545十进制转二进制为00000000 01000001 01000001 01000001.
p_c1不是指向00000000 01000001 01000001 01000001吗?
正在打印 *p_c1,我原以为它是 'A',但它打印了 'P'。 而且它不是因为它是一个随机字符,它总是在每次执行时发生变化,它总是打印 'P'。为什么?
sizeof(char)
保证为1(不管多少位),所以你有char *p_c1 = p - 1;
问题 1:
当您对指针进行加法或减法时,您将地址更改 sizeof(*p)
,因此您不是将地址更改一个字节,而是更改 sizeof(int)
个字节。这是必要的,因为 a[i] == *(a+i)
等效。
问题 2:
你在应该加的时候减了。某物的地址是它开始的地址,所以减去会导致在 a
之外的位置。你想搬进 a
,所以你想添加。
固定:
int a = 0x41424344;
char *p = (char *)&a;
for ( size_t i=0; i<sizeof(int); ++i )
printf( "%zu %d %c\n", i, *(p+i), *(p+i) );
输出因系统而异,但您应该在 little-endian 系统上获得以下内容,其中 char
类型大小为 8 位,int
类型大小为 32 位尺寸:
0 68 D
1 67 C
2 66 B
3 65 A
An integer variable takes 4 bytes
这是一个错误的说法。正确的说法是,如果 CHAR_BIT=8
,整数需要 至少 2 个字节,如果 CHAR_BIT>=16
,则 至少需要 1 个字节。有些系统 CHAR_BIT 是 64,在这样的系统上所有类型都是 sizeof(TYPE) = 1
。这个想法是,int 的大小必须至少为 16 位。有些系统需要进行几次提取才能将整数放入寄存器。
char *p_c1 = p - (1*sizeof(char));
你可以把整型变量int a
想象成一个长度为1的数组,如果取整型的地址,就相当于取数组第一个元素的地址。
你尝试做的是在 a
地址之前取前一个整数(因为 (1 times sizeof(char) )= 1
)并考虑那个的第一个字节整数。这是不正确的,访问超出其限制的数组或访问未明确分配给变量的地址是未定义的行为。
正如@ikegami 所说“当你对一个指针进行加法或减法时,你通过 sizeof(*p) 改变了地址”,所以通过类型转换和加 1,我能够访问 a 的第二个字节,现在正在打印 'A'
#include <stdio.h>
int main(){
int a = 4276545;
int *p = &a;
char *p_c1 = (char*) p + 1;
printf("Value of p_c1 (second byte of a) is %c\n", *p_c1);
}
谢谢大家的评论,学到了很多