c - C ( (int*) (char*)) 中的铸造问题
问题描述
所以这是代码,直到第 4 次打印出来我很容易遵循它,但是在第 5 次打印输出时,我不明白
为什么"5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302 "
?
我明白了,a[1]
但我还在想a[2]
256怎么来的?
#include <stdio.h>
#include <stdlib.h>
void f(void)
{
int a[4];
int *b = malloc(16);
int *c;
int i;
printf("1: a = %p, b = %p, c = %p\n", a, b, c);
c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c[1] = 300;
*(c + 2) = 301;
3[c] = 302;
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = c + 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = (int *) ((char *) c + 1);
*c = 500;
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
b = (int *) a + 1;
c = (int *) ((char *) a + 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}
int
main(int ac, char **av)
{
f();
return 0;
}
解决方案
这一行:
c = (int *) ((char *) c + 1);
可能会让您陷入未定义的行为(技术上),但它可以在英特尔处理器上得到可靠解释。
您的第 4 份打印声明显示了这一点:
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
假设 Intel 芯片和 int 的小字节序(很可能),您在和sizeof(int)==4
引用的地址处的内存布局如下。 指向此时。a
c
c
&a[1]
C8 00 00 00 90 01 00 00 2D 01 00 00 2E 01 00 00 XX XX XX
[ A[0] ] [ A[1] ] [ A[2] ] [ A[3] ]
[ C[0] ] [ C[1] ] [ C[2] ]
因此,当您说 时c = (int *) ((char *) c + 1);
,您已经将上面的内存阵列的视图移动了 1 个字节。因此c
现在指向 内的第二个字节A[1]
,或者作为一个扁平数组:
C8 00 00 00 90 01 00 00 2D 01 00 00 2E 01 00 00 XX XX XX
[ A[0] ] [ A[1] ] [ A[2] ] [ A[3] ]
[ C[0] ] [ C[1] ] [ C[2] ]
然后这个语句发生了。
*c = 500;
这将转换C[0]
当前01 00 00 2D
为500
小端十六进制的字节值F4 01 00 00
。调整内存值如下:
| CHANGED |
C8 00 00 00 90 F4 01 00 00 01 00 00 2E 01 00 00 XX
[ A[0] ] [ A[1] ] [ A[2] ] [ A[3] ]
[ C[0] ] [ C[1] ] [ C[2] ]
结果,2D
占用 A[2] 的第一个字节的值现在是00
。
所以 A[2] 包含00 01 00 00
which in little endian 转换为0x00000100
,即256
。
上面的代码有一些违反规则的地方,但是像上面这样进行指针数学运算的代码在C
世界上并不少见,并且由编译器可靠地实现。请注意,在某些架构(例如 Sparc)中,写入在 4 字节边界上未字对齐的整数指针会产生异常(导致程序崩溃的SIGBUS信号)。在操作系统和 Intel/Windows 的 CPU 架构之间的某个地方,这是为您处理的(尽管速度较慢)。
推荐阅读
- html - 如何在 html&css 中的下拉菜单之间放置空格
- python - 我坚持的快速技术 python 问题(python 新手)
- verilog - Verilog中的未知模块错误,但模块已经存在
- php - 按日期转换 Google Charts 中的 PHP 数组格式化数量
- android - Calendar getDisplayName for weekday 在不同的 Android 版本中给出不同的输出
- laravel - Laravel Livewire 超时
- xcode - Fluter Apple 硅致命 Shared_preferences 错误:找不到“Flutter/Flutter.h”文件
- .net - 邮政信箱正则表达式
- windows - 有没有办法让 Git 在 `git push` 中更改它的 ncat 命令?
- r - 使用闪亮更新空间多边形数据框