固定小数点数と浮動小数点数
この記事で言及されているものはすべてIntelx86Cpuに基づいており、開発環境はWindows 10 + vs2019に基づいています。このブログでは、読者が10進数、16進数、2進数の間の変換を理解する必要があります。変換プロセスについては、この記事では紹介しません。関連情報を見つけるには、詳細なプロセスを理解する必要があります。
まず、コンピュータのデータストレージの基礎知識を簡単に紹介します。具体的な内容は、大学のコース「コンピュータ組織の原則」で詳しく説明されています。コンピュータのデータストレージには2つの形式があります。1つは固定小数点数で格納する方法です。つまり、C / C ++ではchar、short、int、long、longlongであり、もう1つは浮動小数点数で保存する方法です。は、C / C ++です。浮動小数点、ダブルイン。
固定小数点数のchar、short、int、long、およびlonglongの格納原理はすべて同じですが、長さが異なるため、詳細に紹介するintタイプと、floatおよびdoubleの浮動小数点の原理を選択します。 -ポイント番号は同じです。詳細に紹介するためにfloatを選択します。
その中で、固定小数点数と浮動小数点数は両方とも符号ビットを示す最上位ビット(0は正の数を示し、1は負の数を示します)であり、残りのビットは値を示し、バイトはフラッシュバックです(少し-エンディアンモード)。これは、上位バイトが左側にあり、下位ワードが右側にあることを意味します。
固定小数点
固定小数点数は比較的単純です。コンピューターは実数値を格納します。コンピューターは4バイト(32ビット)を使用してint変数を格納します。例:int value = 1;次に、値はバイナリに変換されます0000 0000 0000 0000 0000書き込みの便宜のために000000000001。16進数の形式で0000 0001として記述されています。コンピューターはフラッシュバックストレージであるため、コンピューターは01 00 0000として保存されます。
浮動小数点
以下では、浮動小数点数の浮動小数点ストレージを紹介します。C/ C ++の浮動小数点ストレージ標準はIEEE754に基づいています。具体的な内容は、科学的記数法で表現できる値です。つまり、次のように記述できます。
A * 2 ^ n
其中A为尾数,2为底数,n为指数。
底が2であるため、すべてのAは1より大きく2より小さい、つまり、nの累乗で1.xxxx * 2と書くことができます。したがって、スペースを節約するために、コンピューターは1の整数部分。これは、すべての浮動小数点数が1を変換するときに、その1をで数えることができるためです。nは正または負になります(127を追加する必要があります)。
浮動小数点数の格納は、符号+指数+分数で構成されます。
の種類 | サインビット | インデックス | 仮数 |
---|---|---|---|
浮く | 1位(31位) | 8桁(23〜30桁) | 23桁(0〜22桁) |
ダブル | 1位(63位) | 11位(52位から62位) | 52桁(0〜51桁) |
例:float value = 12.5; then
10進数から2進数への方法:整数部分は2で除算され、小数部分は2で乗算されます
フロートコンピュータストレージ(リトルエンディアンモード)すなわち00 00 48 41
ダブルコンピュータストレージ(リトルエンディアンモード)、つまり00 00 00 00 00 00 29 40
メモリ検証結果を表示する
#include<stdio.h>
int main()
{
float a = 12.5;
float* p = &a;
double b = 12.5;
double* pb = &b;
printf("%d\n", a);
printf("%d\n", (int)a);
printf("%d\n", *(int*)&a);
return 0;
}
ブレークポイントを介して変数aおよびbのアドレスを確認し、メモリビューアを使用して、アドレスを介して対応するメモリを確認し、確認します。
VS2019がブレークポイントまで実行されると、メニューdebug-> window-> memory-> memory 1
メモリはだまされていないので、結果は正しく検証されます
ビッグエンドリトルエンド
ビッグエンディアンモード:指数据的高字节保存在内存的低地址
例:12345(0x3039)の保管順序は 0x30、0x39
リトルエンディアンモード:指数据的高字节保存在内存的高地址
例:12345(0x3039)の保管順序は 0x39、0x30
ビッグエンドを判断する
方法1:
#include<stdio.h>
int main(int argc, char *argv[])
{
int i = 0x12345678;
char c = i;
if (c == 0x78)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
方法2:
#include<stdio.h>
int main(void)
{
int a = 0x12345678;
char *p = (char *)&a;
if (0x78 == *p)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
方法3:
#include<stdio.h>
typedef union NODE
{
int i;
char c;
}Node;
int main(int argc, char *argv[])
{
Node node;
node.i = 0x12345678;
if (0x78 == node.c)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
前号の質問4
#include<stdio.h>
int main()
{
float a = 12.5;
printf("%d\n", a);
printf("%d\n", (int)a);
printf("%d\n", *(int*)&a);
return 0;
}
- printf( "%d \ n"、a);
printfはタイプと一致しないため、floatをdoubleに、double 8バイトに、12.5fを16進数に直接変換します:0x40290000 00000000
コンピューターに保存されている値(リトルエンディアンモード)は次のとおりです。000000 00 00 00 29 40
%dの要件は4バイト整数です。ダブルメモリレイアウトの場合、最初の4バイトが00であることがわかります。したがって、出力は当然0です。
- printf( "%d \ n"、(int)a);
Floatは強制的にintに変換され、小数部は省略され、すべて12になります。
- printf( "%d \ n"、(int)&a);
フロート4バイト、バイナリに変換された12.5fは01000001010010000000000000000000、16進数は0x41480000、10進数は1095237632です。
前号の質問10
トピックレビュー:
#include<stdio.h>
int main()
{
int a = 3, b = 5;
printf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]);
//等价printf("Hello! how is this? %s\n", "super");
printf(&a["WHAT%c%c%c %c%c %c !\n"], 1["this"], 2["beauty"], 0["tool"], 0["is"], 3["sensitive"], 4["CCCCCC"]);
return0;
}
ポインターの代替使用法:
char arr[20] = "hello world";
printf("%s\n", arr); //从&arr[0]地址处开始读取字符串到'\n'结束 输出hello world
printf("%s\n", &arr[6]); //从&arr[6]地址处开始读取字符串到'\n'结束 输出world
printf("%s\n", &6[arr]); //从&arr[6]地址处开始读取字符串到'\n'结束 输出world
arr [i]は実際には*(arr + i)であり、これは*(i + arr)であり、文法規則に属しますが、あまり使用されません。
printf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]);
//等价printf("Hello! how is this? %s\n", "super");
ここで「Ya!Hello!これはどうですか?%s \ n」は定数領域に格納されている文字列です
char* p = "Ya!Hello! how is this? %s\n";
char* p1 = "junk/super";
printf(&a[p], &b[p1]);
printf(&p[3], &p1[5]);
ここでの数字の3と5は、アドレスのオフセットです。