データストレージの分析と例

1.元のコード、1の補数、1の補数
符号なし数値の場合、元の1の補数は同じです。
元の1の補数と1の補数
3つの表現方法には、符号ビットと値ビットの2つの部分があります。符号ビットはすべて0で表されます。「正」、1を使用して「負」を表し、値ビットの3つの表現方法が異なります
。①元のコード
バイナリを正と負の数の形式でバイナリに直接変換します
。②逆コード
//元のコードの符号ビットは変更されません。他のビットは順番に
反転することで取得できます。③の補数
//反転されたコードに1を加算します。

int main()
{
    
    
	int a = 20;
	//00000000000000000000000000010100  --原码
	//00000000000000000000000000010100  --反码
	//00000000000000000000000000010100  --补码
	//转化为16进制位
	//0x00000014    在VS的编译器中他的存储方式是小端字节序
	int b = -10;
	//1000000000000000000000001010 -- 原码
	//1111111111111111111111110101 -- 反码
	//1111111111111111111111110110 --补码
	//0xFFFFFFF6 
}

ここに画像の説明を挿入

プラスチック成形の場合:データは実際には補完としてメモリに保存されます。
なぜですか?
1.コンピュータシステムでは、値は常に補数で表され、保存されます。その理由は、補数コードを使用すると、符号ビットと値フィールドを同時に処理できるためです。同時に、加算と減算も同時に処理でき、CPUには加算器しかありません。
。次に、1-1を計算できないかどうかを言います。
1+に変換(-1)

2.
ビッグエンディアンの概要ビッグエンディアンストレージモード:メモリの上位アドレスに格納されている下位データを指し、上位データはメモリの下位アドレスに格納されます。
リトルエンディアンストレージモード:メモリに格納されている下位データを参照します。下位アドレスで
は、データの上位ビットがメモリの上位アドレスに格納されます。VSコンパイラの場合、これはリトルエンディアンストレージモードであり、左側にあります。は下位アドレス、右側は上位アドレスです。低--------- -------高
質問:現在のマシンのエンディアンを判断するための小さなプログラムを設計します。
分析: int a = 10x00000001
ビッグエンディアンモードのような整数の最初のバイトを取り出します0000 0001
リトルエンディアンモード0100 00 00 00が
ビッグエンディアンを意味する場合、01はリトルエンディアンを意味し
ます。ここで決定する関数をカプセル化します。現在のマシンのビッグエンディアン

int check_sys()
{
    
    
	int a = 1;
	char* p = (char*)&a;
	//返回1表示小端
	//返回0表示大端
	return *p;
}
int main()
{
    
    
	int a = 1;
	char* p = (char*)&a; //char* 能表示我当前访问的自己大小
	int ret = check_sys();
	if (ret == 1)
	{
    
    
		printf("小端\n");
	}
	else
	{
    
    
		printf("大端\n");
	}
	return 0;
}

質問2.
何を出力しますか?

int main()
{
    
    
	//10000000000000000000000000000001
	//11111111111111111111111111111110
	//11111111111111111111111111111111
	char a = -1;
	//11111111
	//应为打印的是%d所以这里要发生整形提升,对于char来说是有符号的
	//所以前面补符号位
	//11111111111111111111111111111111 -- 补码
	//原码就是-1
	signed char b = -1;
	//11111111
	//和char的性质一样
	unsigned char c = -1;
	//11111111  最前面的并不是符号位,所以发生整形提升的时候补充0
	//0000000000000000000110011111111
	//所以对应的十进制数就是255
	printf("a = %d,b = %d,c = %d", a, b, c);
	return 0;
}
//结果是 -1 -1 255

質問3.
出力は何ですか?


int main()
{
    
    
	char a = -128;
	//10000000000000000000000010000000 
	//11111111111111111111111101111111
	//11111111111111111111111110000000
	//发生截断
	//10000000
	//11111111111111111111111110000000--补码
	//但是对于一个无符号数来说,原反补是相同的
	//所以a = 4294967168转换为无符号十进制数  是一个很大的数字
	printf("%u\n", a);  //%u--打印十进制的无符号数
	return 0;
}

文字の範囲は
0-127-1 — -128これは、ディスクの左側が上から下に-1であると表現できます—>-128右側が下から上に127です-> 0
全体の範囲は-128-> 127です
ここに画像の説明を挿入

int main()
{
    
    
	char a = -128;
	printf("%u\n", a);
	return 0;
}

//这里你要思考对于一个char类型能存储下一个128吗?
int main()
{
    
    
	char a = 128;  //127 + 1  根据上面的圆盘就知道其实也是打印出来-128的意思
	printf("%u\n", a);
	return 0;
}

1の補数の形式で操作し、最後に符号付き整数にフォーマットします

int main()
{
    
    
	int i = -20;
	unsigned int j = 10;
	//10000000 00000000 00000000 00010100
	//11111111 11111111 11111111 11101011
	//11111111 11111111 11111111 11101100 -- -20补码
	//00000000 00000000 00000000 00001010 -- 10的补码
    //11111111 11111111 11111111 11110110  --结果
	//11111111 11111111 11111111 11110101 -- 结果的补码
	//10000000 00000000 00000000 00001010  -- 结果原码  -10
	printf("%d\n", i + j);
}

結果はどうですか?

#include<windows.h>
int main()
{
    
    
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
    
    
		printf("%u\n", i);
		Sleep(100);// 单位是ms  也就是0.1s 
	}
	return 0;
}
//你会发现对于一个unsigned int 类型的压根就不可能小于0,所以这是一个死循环

古典的な質問

int main()
{
    
    
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
    
    
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}
//结果 255   因为对于char 来说-128 --> 127 的范围,你好好想一下刚才的圆盘-128 -1 = -129  转换过来就是127
//知道他从右下转到右上遇见了字符'0' ,他就停止了

間違った考え:charタイプaで定義された配列は-1、-2…-1000に格納されますが、strlenは\ 0を満たさないため、strlenのサイズはランダムな値です

unsignedchar型の問題

unsigned char i = 0;
int main()
{
    
    
	for (i = 0; i <= 255; i++)
	{
    
    
		printf("hello world\n");
	}
	return 0;
}

結果も無限ループになります。unsignedcharの最大サイズは255しかないため、ループ本体内の条件を満たし続け、「helloworld」を出力し続けます。

3.浮動小数点型のメモリへの格納

int main()
{
    
    
	int n = 9;
	float* pFloat = (float*)&n;// float* 访问的也是4个字节的空间大小
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);

	*pFloat = 9.0;
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	return 0;
}

ここに画像の説明を挿入
分析:ポインタpFloatの場合、メモリに格納されているint = 9の補数は浮動小数点型である必要があると考えられます
000000000000000000 00000000 00001001
0 00000000 00000000000000000001001
復元します:(-1)^ 0 * 0.00000000000000000001001 * 2 ^ -126
無制限0に近いので、0.000000を出力します

* pFloat = 9.0は
(-1)^ 0 * 1.001 * 2 ^ 3の形式で格納され、メモリに格納されます。M= 3 + 127は、バイナリ
0に変換します。100000100100000000000000000000-計算値は、これが補数であり、符号ビットは正を意味します。
注:
ここに画像の説明を挿入
32ビットの場合:
ここに画像の説明を挿入

int main()
{
    
    
	float f = 5.5;
	//5.5
	//101.1
	//(-1)^0 * 1.011 * 2^2
	//S=0
	//M = 1.011
	//E =2
	//E在内存中真正的存储方式是要加127的  把129转化为二进制数
	// 0 10000001 011 00000000000000000000(补齐23位M)一共32位,这才是真正的在内存中存储的二进制序列
	//0x 40 b0 00 00 以16进制的形式展现内存
}

64ビットの場合
ここに画像の説明を挿入
指数Eがメモリから取り出される
場合:1。Eがすべて0またはすべて1でない場合:32ビットの場合は-127が必要であり、64ビットの場合は-1023が必要です。 E値
2. Eはすべて0である。このような場合のためにあなたが考える場合、彼は127を追加しましたし、結果はそれが非常に少ない数である-127、意味、全て0である
0 00000000 01100000000000000000000
0.011 * 2 ^ -126
Eで用をすべて0の場合、復元時にMを1で補完する必要はなく、Eも直接固定値1-127 3に変更されると規定しています
。Eがすべて1の場合:E + 127 = 255、つまり元のE = 1281。
数値xxx * 2 ^ 128は大きすぎて計算できないため、考慮されません。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/MEANSWER/article/details/109692179