以下 C 代码的输出
Output of the following C code
以下 C 代码的输出是什么。假设它在 Little endian 机器上运行,其中 short int 占用 2 个字节,char 占用 1 个字节。
#include<stdio.h>
int main() {
short int c[5];
int i = 0;
for(i = 0; i < 5; i++)
c[i] = 400 + i;
char *b = (char *)c;
printf("%d", *(b+8));
return 0;
}
在我的机器上它给出了
-108
我不知道我的机器是小端还是大端。我在某个地方发现它应该给
148
作为输出。因为404的低8位(即元素c[4])是148。但我认为由于“%d”,它应该从c[4]的地址开始从内存中读取2个字节。
要查看您的系统中类型的大小:
printf("char = %u\n", sizeof(char));
printf("short = %u\n", sizeof(short));
printf("int = %u\n", sizeof(int));
printf("long = %u\n", sizeof(long));
printf("long long = %u\n", sizeof(long long));
更改程序中的行
unsigned char *b = (unsigned char *)c;
printf("%d\n", *(b + 8));
和简单测试(我知道这不能保证,但我知道的所有 C 编译器都是这样做的,我不关心具有不同地址和指向不同类型数据的指针的旧 CDC 或 UNISYS 机器
printf(" endianes test: %s\n", (*b + (unsigned)*(b + 1) * 0x100) == 400? "little" : "big");
再说一句:只是因为在你的程序中c[0] == 400
c[4]
存储 404
。在双字节小端表示法中,这意味着两个字节 0x94
0x01
,或(十进制)148
1
.
b+8
寻址 c[4]
的内存。 b
是指向 char
的指针,因此 8
表示添加 8 个字节(即 4 个两字节短)。也就是说,b+8
指向c[4]
的第一个字节,其中包含148
.
*(b+8)
(也可以写成 b[8]
)取消对指针的引用,从而将值 148
作为 char
。这是实现定义的:在许多常见平台上 char
是一个有符号类型(范围为 -128
.. 127
),所以它实际上不能是 148
.但是如果是无符号类型(范围是0
..255
),那么148
就可以了。
148
的二进制位模式是 10010100
。将其解释为二进制补码可以得到 -108
.
这个 char
值(148
或 -108
的)然后自动转换为 int
因为它出现在可变参数函数的参数列表中(printf
)。这不会更改值。
最后,"%d"
告诉 printf
获取 int
参数并将其格式化为十进制数。
所以,回顾一下:假设您有一台机器
- 一个字节是8位
- 负数使用补码
short int
是 2 个字节
... 那么该程序将输出 -108
(如果 char
是有符号类型)或 148
(如果 char
是无符号类型)。
代码在不同的计算机上给出不同的输出,因为在某些平台上 char
类型默认已签名,而在其他平台上默认未签名。这与字节顺序无关。试试这个:
char *b = (char *)c;
printf("%d\n", (unsigned char)*(b+8)); // always prints 148
printf("%d\n", (signed char)*(b+8)); // always prints -108 (=-256 +148)
默认值取决于平台和编译器设置。您可以使用 GCC 选项 -fsigned-char
和 -funsigned-char
.
控制默认行为
以下 C 代码的输出是什么。假设它在 Little endian 机器上运行,其中 short int 占用 2 个字节,char 占用 1 个字节。
#include<stdio.h>
int main() {
short int c[5];
int i = 0;
for(i = 0; i < 5; i++)
c[i] = 400 + i;
char *b = (char *)c;
printf("%d", *(b+8));
return 0;
}
在我的机器上它给出了
-108
我不知道我的机器是小端还是大端。我在某个地方发现它应该给
148
作为输出。因为404的低8位(即元素c[4])是148。但我认为由于“%d”,它应该从c[4]的地址开始从内存中读取2个字节。
要查看您的系统中类型的大小:
printf("char = %u\n", sizeof(char));
printf("short = %u\n", sizeof(short));
printf("int = %u\n", sizeof(int));
printf("long = %u\n", sizeof(long));
printf("long long = %u\n", sizeof(long long));
更改程序中的行
unsigned char *b = (unsigned char *)c;
printf("%d\n", *(b + 8));
和简单测试(我知道这不能保证,但我知道的所有 C 编译器都是这样做的,我不关心具有不同地址和指向不同类型数据的指针的旧 CDC 或 UNISYS 机器
printf(" endianes test: %s\n", (*b + (unsigned)*(b + 1) * 0x100) == 400? "little" : "big");
再说一句:只是因为在你的程序中c[0] == 400
c[4]
存储 404
。在双字节小端表示法中,这意味着两个字节 0x94
0x01
,或(十进制)148
1
.
b+8
寻址 c[4]
的内存。 b
是指向 char
的指针,因此 8
表示添加 8 个字节(即 4 个两字节短)。也就是说,b+8
指向c[4]
的第一个字节,其中包含148
.
*(b+8)
(也可以写成 b[8]
)取消对指针的引用,从而将值 148
作为 char
。这是实现定义的:在许多常见平台上 char
是一个有符号类型(范围为 -128
.. 127
),所以它实际上不能是 148
.但是如果是无符号类型(范围是0
..255
),那么148
就可以了。
148
的二进制位模式是 10010100
。将其解释为二进制补码可以得到 -108
.
这个 char
值(148
或 -108
的)然后自动转换为 int
因为它出现在可变参数函数的参数列表中(printf
)。这不会更改值。
最后,"%d"
告诉 printf
获取 int
参数并将其格式化为十进制数。
所以,回顾一下:假设您有一台机器
- 一个字节是8位
- 负数使用补码
short int
是 2 个字节
... 那么该程序将输出 -108
(如果 char
是有符号类型)或 148
(如果 char
是无符号类型)。
代码在不同的计算机上给出不同的输出,因为在某些平台上 char
类型默认已签名,而在其他平台上默认未签名。这与字节顺序无关。试试这个:
char *b = (char *)c;
printf("%d\n", (unsigned char)*(b+8)); // always prints 148
printf("%d\n", (signed char)*(b+8)); // always prints -108 (=-256 +148)
默认值取决于平台和编译器设置。您可以使用 GCC 选项 -fsigned-char
和 -funsigned-char
.