此行存储什么值 char c = str[sizeof(int*)] ;?
What value does this line store char c = str[sizeof(int*)] ;?
char str[] = "Stanford University";
char a = str[1];
char b = *(char *)((int *)str + 3);
char c = str[sizeof(int *)];
a
、b
和 c
的字符值是多少?
a = 't'
b
的值是 'v'
,c
是 ' '
(space)。但是c
怎么会是space呢? int *
的大小是 4 个字节或 8 个字节。在这两种情况下我们会有不同的价值观。此外,在 b
中它指向 s[12]
但整行是如何执行的,我的意思是首先它由 int *
类型转换,然后由 char *
类型转换,然后我们取消引用或者我们在做其他事情?
第一个值始终是 't'
,因为它是存储在 str
.
中的 C 字符串中的第二个字符
第二个值取决于 int
在目标平台上的大小。提示:大多数现代平台使用 32 位 int
和 8 位 char
.
第三个值取决于指向 int
的指针的大小。提示:指针的大小可以不同于 int
,在现代平台上它们通常有 64 位。
您在平台上观察到的值与大小为 4 字节(32 位)的 int
和大小为 8 字节(64 位)的 int *
一致。当前的64位系统就是这种情况。
第二个表达式的解释如下:
为了计算 *(char *)((int *)str + 3)
,编译器首先将 str
转换为指向 int
的指针,这可能是未对齐的 (*),然后计算 (int *)str
指向的数组中第四个 int
的地址,因此从该数组的开头算起 12 个字节,然后将此地址转换回 char *
,保持不变地址。最后,*
读取后者指向的字符,因此 str[3 * 4]
即。字母 'v'
.
第三个表达式的行为更容易解释:
char c = str[sizeof(int *)];
只是读取偏移量 sizeof(int *)
处的字符,即 8
或您的系统,因此 c
包含 ' '
,space 在 Stanford
和 University
之间。
请记住,第二个和第三个表达式都是实现定义的:
- 在使用小型模型的旧 MS/DOS 系统上,您将有
b = 'r'
和 c = 'a'
,而在使用中型和大型模型时,您将有 b = 'r'
和 c = 'f'
;
- 在旧的 32 位 Windows、Mac 和 linux 系统上,您将有
b = 'v'
和 c = 'f'
;
- 在某些具有 64 位
int
的奇特 Cray 系统上,计算 b
会出现未定义的行为;
- 在某些嵌入式 DSP 处理器上,您甚至可以有
b = 'n'
和 c = 't'
。
(*) 未对齐的指针将不会作为 int *
取消引用,但即使只是计算无效地址也会有未定义的行为,所以有些东西怪异的系统可能会发生奇怪的事情。如果您的目标是个人计算机 运行 Windows、macOS 或 linux,这种有风险的地址计算应该不会造成问题。
char str[] = "Stanford University";
char a = str[1];
char b = *(char *)((int *)str + 3);
char c = str[sizeof(int *)];
a
、b
和 c
的字符值是多少?
a = 't'
b
的值是 'v'
,c
是 ' '
(space)。但是c
怎么会是space呢? int *
的大小是 4 个字节或 8 个字节。在这两种情况下我们会有不同的价值观。此外,在 b
中它指向 s[12]
但整行是如何执行的,我的意思是首先它由 int *
类型转换,然后由 char *
类型转换,然后我们取消引用或者我们在做其他事情?
第一个值始终是 't'
,因为它是存储在 str
.
第二个值取决于 int
在目标平台上的大小。提示:大多数现代平台使用 32 位 int
和 8 位 char
.
第三个值取决于指向 int
的指针的大小。提示:指针的大小可以不同于 int
,在现代平台上它们通常有 64 位。
您在平台上观察到的值与大小为 4 字节(32 位)的 int
和大小为 8 字节(64 位)的 int *
一致。当前的64位系统就是这种情况。
第二个表达式的解释如下:
为了计算 *(char *)((int *)str + 3)
,编译器首先将 str
转换为指向 int
的指针,这可能是未对齐的 (*),然后计算 (int *)str
指向的数组中第四个 int
的地址,因此从该数组的开头算起 12 个字节,然后将此地址转换回 char *
,保持不变地址。最后,*
读取后者指向的字符,因此 str[3 * 4]
即。字母 'v'
.
第三个表达式的行为更容易解释:
char c = str[sizeof(int *)];
只是读取偏移量 sizeof(int *)
处的字符,即 8
或您的系统,因此 c
包含 ' '
,space 在 Stanford
和 University
之间。
请记住,第二个和第三个表达式都是实现定义的:
- 在使用小型模型的旧 MS/DOS 系统上,您将有
b = 'r'
和c = 'a'
,而在使用中型和大型模型时,您将有b = 'r'
和c = 'f'
; - 在旧的 32 位 Windows、Mac 和 linux 系统上,您将有
b = 'v'
和c = 'f'
; - 在某些具有 64 位
int
的奇特 Cray 系统上,计算b
会出现未定义的行为; - 在某些嵌入式 DSP 处理器上,您甚至可以有
b = 'n'
和c = 't'
。
(*) 未对齐的指针将不会作为 int *
取消引用,但即使只是计算无效地址也会有未定义的行为,所以有些东西怪异的系统可能会发生奇怪的事情。如果您的目标是个人计算机 运行 Windows、macOS 或 linux,这种有风险的地址计算应该不会造成问题。