高度なC言語の救世主(メモリ内のデータストレージ--9)

コンテンツ

1.1データ型の概要

1.2タイプの基本的な分類

2.1メモリ内の形状の保存

2.2元のコード、逆コード、補完コード

2.3ビッグエンディアンストレージとスモールエンディアンストレージ(バイトでソート)

Baidu 2015システムエンジニアはテストの質問を書きました:

2.4符号付き文字と符号なし文字はメモリに保存されます

2.5符号なし整数に負の数を入れるとどうなりますか

3.1運動

4.1メモリ内の浮動小数点ストレージ

4.2浮動小数点ストレージルール 

浮動小数点数は精度を失う可能性があり、正確に格納できません

インデックスEはメモリからフェッチされ、さらに3つのケースに分けることができます。


 

1.1データ型の概要

char 文字データ型
短い         短整数
int 整数
長さ 長整数、C言語、long> = int
長い長い より長い成形
浮く 単精度浮動小数点数
ダブル 倍精度浮動小数点数

 

タイプの意味:

1.このタイプを使用して、メモリスペースのサイズを開きます(サイズによって使用範囲が決まります)

2.記憶空間の視点を見る方法。

1.2タイプの基本的な分類

1.整形家族


char//虽然是字符类型,但是字符类型存储的时候存放的是字符的ASCII码值,是整数 
    //C语言没定义char是否为有符号还是无符号,取决于编译器

 unsigned char
 signed char

short //默认为有符号
 unsigned short [int]
 signed short [int]

int //默认为有符号
 unsigned int
 signed int

long  //默认为有符号
 unsigned long [int]
 signed long [int]



2.浮点数家族

float  //默认为有符号
double  //默认为有符号


3.构造类型(自定义类型)

> 数组类型
> 结构体类型 struct
> 枚举类型 enum
> 联合类型 union



4.指针类型
int *pi;
char *pc;
float* pf;
void* pv;//空类型:void 表示空类型(无类型)通常应用于函数的返回类型、函数的参数、指针类型。

温度:(-5 10)には正と負のデータがあり、符号付き変数に格納できます

年齢(正の数のみ)符号なし変数に配置できるのは正の数のみ


2.1メモリ内の形状の保存

2.2元のコード、逆コード、補完コード

コンピュータの整数の表現方法には、元のコード、逆コード、補数コードの3つがあります。

3つの表現方法には、符号ビットと値ビットの2つの部分があります。符号ビットは、「正」の場合は0、「負」の場合は1です。

負の整数の3つの表現は異なります。

正の数の元の、逆の、および補数は同じです。シェーピングの場合:メモリに保存されているデータは、実際には補数コードを保存します。

//整数可以写出三种2进制表示形式:
//原码:直接将数值按照正负数的形式翻译成二进制就可以
//反码:将原码的符号位不变,其他位依次按位取反就可以得到了
//补码:反码+1就得到补码。

int main()
{
	int a = 10;//整型值
	//原码:00000000000000000000000000001010
	//反码:00000000000000000000000000001010
	//补码:00000000000000000000000000001010

	int b = -10;//整型值
	//原码:10000000000000000000000000001010
	//反码:11111111111111111111111111110101
	//补码:1111 1111 1111 1111 1111 1111 1111 0110
	//      F    F    F     F   F     F    F   6
	在内存中存放的十六进制为是:0xff ff ff f6吗?
	//
	return 0;
}


//正整数的原码、反码、补码相同
//负数的原码、反码、补码是需要计算的

bデータはF6FFFF FFとしてメモリに保存されていることがわかります。これは、大小の端があるため、逆さまに保存されます。

int main()
{
	int a = 0x11223344;

	return 0;
}

 

2.3ビッグエンディアンストレージとスモールエンディアンストレージ(バイトでソート)

ビッグエンディアンバイトオーダー(ストレージ)モードとは、データの下位ビットがメモリの上位アドレスに格納され、データの上位ビットがメモリの下位アドレスに格納されることを意味します。

リトルエンディアン(ストレージ)モードとは、データの下位ビットがメモリの下位アドレスに格納され、データの上位ビットがメモリの上位アドレスに格納されることを意味します。

int main()
{
	int a = 0x11223344;

	return 0;
}

 なぜ大小のエンディアンモードがあるのですか?これは、コンピュータシステムでは、バイトを1単位として使用し、各アドレス単位が1バイトに対応し、1バイトが8ビットであるためです。ただし、16ビットのショートタイプと32ビットのロングタイプもあります。また、16ビットや32ビットプロセッサなど、8ビットを超えるプロセッサの場合、レジスタ幅が1バイトを超えるため、複数のバイトをどのように配置するかという問題です

 

Baidu 2015システムエンジニアはテストの質問を書きました:

ビッグエンディアンのバイトオーダーとリトルエンディアンのバイトオーダーの概念を簡単に説明し、現在のマシンのバイトオーダーを決定するための小さなプログラムを設計してください。

思路:例如刚刚的0x11223344,我们只需要判断第一个字节是不是11即可

//00000000000000000000000000000001
//0x 00 00 00 01


int check_sys()
{
	int a = 1;
	char* p = (char*)&a;//向后访问一个字节
	return *p;
}

//int check_sys()//第二种写法
//{
//	int a = 1;
//	return *(char*)&a;
//}

int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}

2.4符号付き文字と符号なし文字はメモリに保存されます

符号付きの値-128〜127

符号なしの値0〜255

注:10000000は、符号付きビットで-128として直接解析されます


2.5符号なし整数に負の数を入れるとどうなりますか


#include <stdio.h>

int main()
{
	unsigned int ch = -10;//作用1:创建变量时指定大小 
                          //作用2:这个符号数怎么被理解取决于你如何使用
	//-10
	//10000000000000000000000000001010
	//11111111111111111111111111110101
	//11111111111111111111111111110110
	
	//printf("%u\n", ch);//结果是非常大的整数   %u是打印无符号数
    //意思是你要我打印的一定是无符号数,不是无符号数,我也认为是无符号数
	

    printf("%d\n", ch);//结果是-10    %d是打印有符号数
    //11111111111111111111111111110110转换成原码
    //意思是你要我打印的一定是有符号数,不是有符号的数,我也认为是有符号数
	return 0;
}

負の数を符号なし整数に入れてさまざまな方法で出力することは、実際にはコンパイラをバイナリビットで動作させることです。符号がある場合、最上位ビットは符号ビットとして理解され、1は負の数、0は負の数です。整数です


3.1運動

//输出什么?
#include <stdio.h>
int main()
{
    char a= -1;
    signed char b=-1;
    unsigned char c=-1;
    printf("a=%d,b=%d,c=%d",a,b,c);
    return 0;
}
//输出什么?
#include <stdio.h>
int main()
{
    char a= -1;
//10000000000000000000000000000001
//11111111111111111111111111111110
//11111111111111111111111111111111
//发生截断,保留11111111 ,以%d打印,发生整型提升,最高位补符号位//11111111111111111111111111111111
 结果为-1
    signed char b=-1;
//10000000000000000000000000000001
//11111111111111111111111111111110
//11111111111111111111111111111111
//发生截断,保留11111111  以%d打印,发生整型提升,最高位补符号位//11111111111111111111111111111111
结果为-1

    unsigned char c=-1;
//10000000000000000000000000000001
//11111111111111111111111111111110
//11111111111111111111111111111111
//发生截断,保留11111111,以%d打印,整型提升,无符号数高位直接补零
//00000000000000000000000011111111
结果为255

    printf("a=%d,b=%d,c=%d",a,b,c);//a=-1 b=-1 c=255
    return 0;
}

3.2次のプログラムの出力は何ですか?

#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0;
}
#include <stdio.h>
int main()
{
    char a = -128;//~128-127
//1000000000000000000000010000000  ---128的原码
//1111111111111111111111101111111  反码
//1111111111111111111111110000000  补码
,发生截断,保留10000000
//以%u打印(无符号整数),进行整型提升,由于a是char类型,
//11111111111111111111111110000000原码
//因为按照%u进行打印,我们认为这个数字是一个正数
答案是一个很大的是数字//4,294,967,168
    printf("%u\n",a);
    return 0;
}

3.3次のプログラムの出力は何ですか?

#include <stdio.h>
int main()
{
    char a = 128;
//00000000000000000000000010000000
//截断10000000
//整型提升11111111111111111111111110000000
//以%u打印,很大的正数
    printf("%u\n",a);
    return 0;
}

3.4次のプログラムの出力は何ですか?

int i= -20;
unsigned  int  j = 10;
printf("%d\n", i+j); 
//按照补码的形式进行运算,最后格式化成为有符号整数

int main()
{
	int i = -20;
	//10000000000000000000000000010100
	//11111111111111111111111111101011
	//11111111111111111111111111101100 ~ -20的补码
	//
	unsigned int j = 10;
	//00000000000000000000000000001010
	//00000000000000000000000000001010
	//00000000000000000000000000001010

	printf("%d\n", i + j);//-10
	//11111111111111111111111111101100
	//00000000000000000000000000001010

	//11111111111111111111111111110110 - 相加后的结果,补码
	//11111111111111111111111111110101 - 反码
	//10000000000000000000000000001010 - 原码

    //答案是-10
	return 0;
}

3.5次のプログラムを実行した結果はどうなりますか?

int main()
{
	unsigned int i;

	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);//对一个无符号数来说,最小值是0
	}

	return 0;
}

//死循环,当i--变成-1时,11111111111111111111111111111111被理解为一个很大的数
// i==很大的数 继续循环--


3.6次のプログラムの出力は何ですか?

int main()
{
    char a[1000]; 
    int i;
    for(i=0; i<1000; i++)
   {
        a[i] = -1-i;   //char取值范围~128-127
   }
    printf("%d",strlen(a));
    return 0;
}

解题思路:strlen是求字符串长度的,找的'\0'的位置,统计的\0之前出现多少个字符
'\0'的ASCII码值是0

答案是255,还记得上面画的那张char类型数据图么,逆时针循环直到遇到\0停下

4.1メモリ内の浮動小数点ストレージ

下面这题的4个结果是什么?

int main()
{
 int n = 9;
 float *pFloat = (float *)&n;
 printf("n的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 *pFloat = 9.0;//找到了n
 printf("num的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 return 0;
}

 

numと*pFloatは明らかにメモリ内の同じ数ですが、浮動小数点数と整数の解釈結果がそれほど異なるのはなぜですか?

この結果を理解するには、浮動小数点数がコンピューターの内部でどのように表されるかを理解する必要があります。

n = 9、整数の形で入れて、整数の形で印刷してください、問題ありません

* pFloat = 0.000000なぜですか?整数の格納方法はメモリ内の浮動小数点数の格納方法とは異なるため、浮動小数点ポインタは逆参照され、メモリ内のデータは浮動小数点数と見なされます。

3番目の*pFloatは非常に大きな数値であり、浮動小数点数の形式で入力し、整数の形式で取得すると、結果が異なります。

4.2浮動小数点ストレージルール 

国際規格IEEE(Institute of Electrical and Electronics Engineering)754によると、任意の2進浮動小数点数Vは次の形式で表すことができます。

(-1)^ S * M * 2 ^ E

(-1)^ sは符号ビットを表し、s = 0の場合、Vは正であり、s = 1の場合、Vは負です。

Mは、1以上2未満の有意な数を表します。

2^Eは指数ビットを意味します。

例:5.5はビットで101.1です

 浮動小数点ストレージに変換する

別の浮動小数点数を変換してみましょう

浮動小数点数は精度を失う可能性があり、正確に格納できません


浮動小数点数のメモリへの格納方法

32ビット浮動小数点数の場合、最上位1ビットは符号ビットs、次の8ビットは指数E、残りの23ビットは仮数Mです。

64ビット浮動小数点数の場合、最上位1ビットは符号ビットS、次の11ビットは指数E、残りの52ビットは仮数Mです。

 

前述のように、1≤M<2、つまりMは1.xxxxxxの形式で記述できます。ここで、xxxxxxは小数部分を表します。

デフォルトでは、この番号の最初の桁は常に1であるため、破棄でき、次のxxxxxx部分のみが保存されます。

読むときは、最初の1を追加します。

インデックスEに関しては、状況はより複雑です。

まず、Eはunsigned integer(unsigned int)です。これは、Eが8ビットの場合、その値の範囲は0〜255であり、Eが11ビットの場合、その値の範囲は0〜2047であることを意味します。ただし、科学的記数法のEは負になる可能性があることを私たちは知っています

例:0.5->(binary)0.1-> 1.0 * 2 ^ -1、M = 1.0、E = -1

したがって、IEEE 754では、メモリに格納するときにEの実際の値に中間数値を加算する必要があると規定されています。8ビットEの場合、この中間数値は127です。11ビットEの場合、この中間数値は1023です。たとえば、2 ^ 10のEは10であるため、32ビット浮動小数点数として格納する場合は、10 + 127 = 137、つまり10001001として格納する必要があります。

インデックスEはメモリからフェッチされ、さらに3つのケースに分けることができます。

Eがすべて0またはすべて1ではない このとき、浮動小数点数は次の規則で表されます。つまり、指数Eの計算値を127(または1023)から減算して実数を取得し、有効数字Mに次の規則を加算します。最初の1。たとえば、E = -1が0.5の場合、その注文コードは-1 + 127 = 126であり、01111110として表されます。
Eはすべて0です このとき、浮動小数点数の指数Eは実際の値である1-127(または1-1023)に等しく、有効数字Mは最初の1に加算されなくなりますが、に復元されます。 0.xxxxxxの小数。これは、±0、および0に近い非常に小さい数値を表すために行われます。
Eはすべて1です このとき、有効数字Mがすべて0の場合、±無限大を意味します(正または負は符号ビットsによって異なります)

举个例子
int main()
{
	
	float f = 5.5;
	//
	//101.1
	//(-1)^0 * 1.011 * 2^2
	//S = 0
	//E = 2   +127 = 129
	//M = 1.011
	//存储到内存:
	//0 10000001 01100000000000000000000
	//0x40b00000 
	//
	return 0;
}


元の質問に戻る

int main()
{
	int n = 9;
	//
	//00000000000000000000000000001001
	//0 00000000 00000000000000000001001
	//E = -126
	//M = 0.00000000000000000001001
	//S = 0
	//(-1)^0 *  0.00000000000000000001001 * 2^-126
	//1 * 0.00000000000000000001001 * 2^-126一个超级超级小的数字
	float* pFloat = (float*)&n;//int*
	printf("n的值为:%d\n", n);//9
	printf("*pFloat的值为:%f\n", *pFloat);//0.000000

	*pFloat = 9.0;
	//9.0
	//1001.0
	//1.001 * 2^3
	//(-1)^0 * 1.001 * 2^3
	//S = 0
	//M = 1.001
	//E = 3   +127
	//01000001000100000000000000000000一个很大的数字
	//
	printf("num的值为:%d\n", n);//1,091,567,616
	printf("*pFloat的值为:%f\n", *pFloat);//9.0

	return 0;
}

おすすめ

転載: blog.csdn.net/weixin_63543274/article/details/123791139