一道好题
今天在看linux C 语言编程时遇到一道很不错的题目,觉得有必要记录下来并在讲解上作适当延申。
题如下:问最终输出多少?ps:在原题的基础上我增加了 printf("a_sizeof = %d\n",sizeof(a));
#include<stdio.h> void main() { int i = 0; char a[1000]; for(i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("a_strlen = %d\n",strlen(a)); printf("a_sizeof = %d\n",sizeof(a)); system("pause"); }
最终打印输出的是:a_strlen = 255
a_sizeof = 1000
关于这个题,主要涉及到一下几个方面:
1.数据类型与类型转换
a 是一个char型数组,长度为1000,每个元素的取值范围为 -128~127(-2^7 ~ 2^7 - 1);
i 是一个int型变量,取值范围为-2^31 ~ 2^31 - 1;
a[i] = -1 - i;运算过程中,首先 (-1 - i)得到一个int 型数据,最后转换成char型,赋给a[i];
2.数据计算机中的存储及加减运算
在计算机内存中,任何数据都是以二进制的补码形式存储的,这样做的一个好处就是减法可以当作加法来做,补码相加,舍去进位;
补码计算:整数的补码与其原码 反码相同,如 十进制 +4,原码 0000 0100,反码 0000 0100,补码 0000 0100;
负数的补码,反码加1,得到补码,如十进制-1,原码 1000 0001,除符号位外其余位按位取反得到反码 1111 1110,反码加1得到补码 1111 1111,即 0xFF;
特例:在8位有符号数据类型中,-128 的原码 反码和补码都为1000 0000
对于有符号数,二进制最高位用作正负数标识,整数最高位为0,负数最高为1,
3.strlen() 和 sizeof()
strlen() 用于计数字符串中字符的个数(即字符串长度),直到遇到'\0'停止,并返回计数值(不包含'\0');
sizeof() 用于计算变量占用内存空间的大小。
经过上面的简单讲解,现在来看看上面问题结果的由来吧!
先来看看,经过for循环后,数组a中各元素的值:
i的值 a[i]的值 a[i]在内存中的存储形式
0 -1 - 0 1111 1111 即 0xFF -1
1 -1 - 1 1111 1110 即 0xFE -2
2 -1 - 2 1111 1110 即 0xFD -3
…… …… ……
127 -1 - 127 1000 0000 即 0x80 -128
128 -1 - 128 0111 1111 即 0x7F 127 溢出(下同)
129 -1 - 129 0111 1110 即 0x1E 126
…… …… ……
254 -1 - 254 0000 0001 即 0x01 1
255 -1 - 255 0000 0000 即 0x00 0
256 -1 - 256 1111 1111即 0xFF -1
…… …… ……
注意,a[255] = 0,即为ascii中的空格字符,strlen(a)计数到a[255]后停止,并返回计数结果255.