我认为C中的整数首先以最高有效位存储,例如,数字5
将是0...0101
。我以为我可以通过强制C让我假装一个特定的内存地址是int
并像在int
一样向其中添加位来操纵特定位。
我试图在内存中设置0的0位,然后尝试将255
添加到不同的内存地址,这似乎工作起来好像最低有效位先于最高有效位存储在内存中,因为当我在我的内存地址中加1并更改位,然后得到一个更大的数字,而不是一个较小的数字。如果最高有效位较早地存储在内存中,则将255
添加到比其高1个字节的内存地址中完全不会影响原始地址的编号,因为后8位是下一个{{ 1}}。我想知道我是否正确地解释了这一点,并且整数首先以最低有效位存储。
int
预期输出:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int main() {
int *x = malloc(8); //getting 4 memory addresses
int *y = malloc(8);
int *z = malloc(8);
int *a = malloc(8);
x[0] = 0; //setting 64 bits past memory addresses to 0s
x[1] = 0;
y[0] = 0;
y[1] = 0;
z[0] = 0;
z[1] = 0;
a[0] = 0;
a[1] = 0;
*((int*)((int)x)) = 255; //adding to x's memory address
*((int*)((int)y + 1)) = 255; //adding 1 byte over from y
*((int*)((int)z + 2)) = 255; //adding 2 bytes over from z
*((int*)((int)a + 3)) = 255; //adding 3 bytes over from a
printf("%d\n", sizeof(int));
printf("%d,%d\n", x[0], x[1]);
printf("%d,%d\n", y[0], y[1]);
printf("%d,%d\n", z[0], z[1]);
printf("%d,%d\n", a[0], a[1]);
printf("%d\n", x);
printf("%d\n", &x[1]);
return 0;
}
实际输出:
4
255,0
0,-16777216
0,16711680
0,65280
12784560
12784564
答案 0 :(得分:5)
我认为c中的int首先存储了最高有效位,例如,数字5将为0 ... 0101
不,这取决于您的平台和工具链,而不取决于C。
您描述的方案(几乎)被称为 big-endian 。
当今许多商用PC是little-endian,所以相反(最低有效字节在前)。您可能就是这种情况。
请注意,字节序是指字节,而不是位。
最好不要尝试像这样操作数据。使用该语言,使用不关心字节序的逻辑运算。
答案 1 :(得分:0)
您的代码中存在一些问题:
位和字节之间似乎有些混淆。计算机内存可按字节寻址,在当前体系结构上通常包含8位。
您不应将指针强制转换为int
,int
可能没有足够的范围来容纳指针的值。将指针转换为unsigned char *
以修补单个字节,但要注意,由于别名规则,这可能不会产生预期的结果:
((unsigned char *)x)[0] = 255; //adding to x's memory address
((unsigned char *)y)[1] = 255; //adding 1 byte over from y
((unsigned char *)z)[2] = 255; //adding 2 bytes over from z
((unsigned char *)a)[3] = 255; //adding 3 bytes over from a
类似地,您应该使用%zu
打印size_t
或将size_t
转换为int
。
(void*)
,并用%p
打印。int
值,更改的效果将更加明显。这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
int main() {
// getting 4 memory addresses, each with enough space for 2 int, initialized to 0
int *x = calloc(2, sizeof(int));
int *y = calloc(2, sizeof(int));
int *z = calloc(2, sizeof(int));
int *a = calloc(2, sizeof(int));
((unsigned char *)x)[0] = 255; //adding to x's memory address
((unsigned char *)y)[1] = 255; //adding 1 byte over from y
((unsigned char *)z)[2] = 255; //adding 2 bytes over from z
((unsigned char *)a)[3] = 255; //adding 3 bytes over from a
printf("%d\n", (int)sizeof(int));
printf("%08x,%08x -- %d,%d\n", x[0], x[1], x[0], x[1]);
printf("%08x,%08x -- %d,%d\n", y[0], y[1], y[0], y[1]);
printf("%08x,%08x -- %d,%d\n", z[0], z[1], z[0], z[1]);
printf("%08x,%08x -- %d,%d\n", a[0], a[1], a[0], a[1]);
printf("%p\n", (void *)x);
printf("%p\n", (void *)&x[1]);
return 0;
}
输出:
4 000000ff,00000000 -- 255,0 0000ff00,00000000 -- 65280,0 00ff0000,00000000 -- 16711680,0 ff000000,00000000 -- -16777216,0 0x7fd42ec02630 0x7fd42ec02634
从上面的输出中,我们可以看到:
int
有4个字节int
的最低有效字节与您存储的最低有效字节相同,这被称为您期望的是相反的 big-endian架构,这种架构在当前的台式机和笔记本电脑上很少见,但在嵌入式架构和手机上很常见。
两种方法都有优点和缺点。 C透明地支持两者,因此大多数程序员并不了解这些复杂性,但是了解这些实现细节在某些情况下非常有用: