有符号数的最高位为符号位,0为正数,1为负数,其余位为数的真值。
大小端指的是字节序。 大端模式:数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。 这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,数据从高位往低位放;这和我们的阅读习惯一致。 小端模式:数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。 这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
unsigned char 表示是无符号的字符类型,即8个比特位放置的都是有效数字,存储范围是0255(0000000011111111)。 a和b的值都在存储范围内。c的值变为300后超出了unsigned char最大可存放的范围。
printf语句打印时候,第一个%d计算a+b的值,只计算不存储,c是执行了a+b之后的结果。
::: tip
a和b两个char类型的变量在相加时候会发生整型提升。
无符号数整型提升时高位补0。
有符号数整型提升高位补符号位。
:::
计算如下:
int main()
{
unsigned char a = 200;
//11001000 - 200
unsigned char b = 100;
//01100100 - 100
unsigned char c = 0;
c = a + b;
//00000000000000000000000011001000 - char a整型提升
//00000000000000000000000001100100 - char b整型提升
//00000000000000000000000100101100 - a+b
//0101100 - char c
//以%d的形式打印时需要整型提升
//00000000000000000000000001011000 - char c整型提升
//c的值存储进char类型,截断后为00101100,转换为十进制为44
printf("%d %d", a + b, c);
return 0;
}
%d打印十进制的有符号数,内存中是有符号数的补码,c的符号位是0,是正数的补码,正数的原反补相同,将a+b的值00000000000000000000000100101100转成十进制数打印出来得到300,将c的值00000000000000000000000001011000转成十进制数打印出来得到44。
十六进制的一个位表示四个二进制位。0x1234就是16个二进制位,即两个字节,int类型大小是4个字节,剩余空间使用0填充,即0x1234 == 0x00001234。 &a取出a的地址,a是整型的地址,强制类型转换成unsigned char类型后解引用,只能访问一个字节的空间。 *大端模式的存储方式是:低位放在高地址,高位放在低地址。** 按照大端模式存储时,a的字节序为00 00 12 34,强制类型转换成unsigned char *类型后解引用时,只能访问到一个字节的内容,即00。b的值为00。
#include <string.h>
int main()
{
char a[1000] = { 0 };
int i = 0;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a)); //255
return 0;
}
数组a中有1000个元素,每个元素是一个有符号的char类型(范围是128~127)。 通过for循环在数组中填充内容。i逐步增加,-1-i逐步减小,从a[i]的值随着i从0增加到127时,a[i]由-1变为-128。i变为1时,a[i]变为127,然后继续变为126、125...2、1、0、-127...直到填满整个数组。 strlen求字符串长度时遇到“/0”停止,即在第一次a[i]的值为0时,strlen的计算就停止了。从-1到-128共128个元素,从127到1共127个元素,共255个元素。
打印杨辉三角
int main()
{
int i = 0;
int j = 0;
int arr[10][10] = { 0 };
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
if (j == 0)
{
arr[i][j] = 1;
}
if (i == j)
{
arr[i][j] = 1;
}
if (j > 0 && i > 1)
{
arr[i][j] = arr[i-1][j-1]+arr[i-1][j];
}
}
}
for (i = 0; i < 10; i++)
{
for (j = 0; j <= i ; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
将a,b,c,d所说的话认为是一个条件,当条件为真时输出1条件为假时输出0。假设凶手是c,a,b,d的值都为1,c为0,相加和为3。
int main()
{
int killer = 0;
for (killer = 'a'; killer <= 'd'; killer++) //kiler在a到d之间
{
if ((killer != 'a') + (killer == 'c') + (killer == 'd') + (killer != 'd') == 3)
{
printf("killer = %c\n", killer);
}
}
return 0;
}
五名选手的名次可能是1、2、3、4、5,可以写5个for循环嵌套。每个选手做了两个判断,各说对一半,可以认为每个选手的两个判断各当成一个条件,一个为真一个为假,即和为0。
int main()
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
for (a = 0; a <= 5; a++)
{
for (b = 0; b <= 5; b++)
{
for (c = 0; c <= 5; c++)
{
for (d = 0; d <= 5; d++)
{
for (e = 0; e <= 5; e++)
{
if (((b == 2) + (a == 3) == 1) &&
((b == 2) + (e == 4) == 1) &&
((c == 1) + (d == 2) == 1) &&
((c == 5) + (d == 3) == 1) &&
((e == 4) + (a == 1) == 1))
{
if (a * b * c * d * e == 120)
{
printf("a=%d,b=%d,c=%d,d=%d,e=%d", a, b, c, d, e);
}
}
}
}
}
}
}
return 0;
}
a=3,b=1,c=5,d=2,e=4
上述代码中第24行if判断不存在时输出的结果如下:
a=1,b=2,c=1,d=3,e=0
a=1,b=2,c=1,d=3,e=1
a=1,b=2,c=1,d=3,e=2
a=1,b=2,c=1,d=3,e=3
a=1,b=2,c=1,d=3,e=5
a=1,b=2,c=5,d=2,e=0
a=1,b=2,c=5,d=2,e=1
a=1,b=2,c=5,d=2,e=2
a=1,b=2,c=5,d=2,e=3
a=1,b=2,c=5,d=2,e=5
a=3,b=0,c=1,d=3,e=4
a=3,b=0,c=5,d=2,e=4
a=3,b=1,c=1,d=3,e=4
a=3,b=1,c=5,d=2,e=4
a=3,b=3,c=1,d=3,e=4
a=3,b=3,c=5,d=2,e=4
a=3,b=4,c=1,d=3,e=4
a=3,b=4,c=5,d=2,e=4
a=3,b=5,c=1,d=3,e=4
a=3,b=5,c=5,d=2,e=4
上述代码中第24行的if的作用是从多个名次重复的答案中选出符合要求的排名。