今日、char変数(1バイト)を宣言すると、アセンブラーは実際にはメモリ内で4バイトを使用するため、境界はワードサイズの倍数になることを学びました。
とにかくchar変数が4バイトを使用する場合、それをcharとして宣言する意味は何ですか?それをintとして宣言してみませんか?同じ量のメモリを使用していませんか?
アセンブリ言語で記述していて、文字のスペースを宣言する場合、アセンブラは1つの文字にスペースを割り当てます。(一般的なアセンブラーに関して記述します。)オブジェクトをアセンブリ言語で整列させたい場合は、その目的のためにアセンブラーディレクティブを含める必要があります。
Cで記述し、コンパイラがそれをアセンブリコードやマシンコードに変換する場合、文字のスペースが埋め込まれることがあります。通常、これは文字オブジェクトの配置の利点のために行われませんが、プログラムでいくつかのことが宣言されているためです。たとえば、次のように宣言するとどうなるかを考えてみましょう。
char a;
char b;
int i;
char c;
double d;
ナイーブなコンパイラはこれを行うかもしれません:
a
ます。これは、たまたま16バイトの倍数にアラインされます。b
。int i
4バイトを必要とするを配置します。このマシンでは、int
オブジェクトを4バイトの倍数に揃える必要があります。そうしないと、オブジェクトにアクセスしようとするプログラムがクラッシュします。したがって、コンパイラは2バイトをスキップしてから、のために4バイトを確保しますi
。c
。d
。これによりd
、8バイトの倍数にアラインされます。これは、この架空のマシンで役立ちます。したがって、ナイーブなコンパイラを使用しても、文字オブジェクトはそれ自体に4バイト全体を必要としません。隣接するキャラクターオブジェクト、またはより大きな配置を必要としない他のオブジェクトと共有できます。しかし、いくらかの無駄なスペースがあります。
よりスマートなコンパイラはこれを行います:
d
。i
。は、8バイトの倍数にアラインされた8バイトのオブジェクトであるi
ため、4バイトの倍数にアラインされていることに注意してください。d
a
最も制限の少ないオブジェクトを配置します。 、、、b
および。にそれぞれ1バイトを確保しc
ます。この種の並べ替えはスペースの浪費を回避し、適切なコンパイラーはそれを自由に配置できるメモリー(スタック上の自動オブジェクトやグローバル・メモリー内の静的オブジェクトなど)に使用します。
構造体内でメンバーを宣言する場合、コンパイラーはメンバーを宣言する順序を使用する必要があるため、スペースを節約するためにこの並べ替えを実行することはできません。その場合、キャラクターオブジェクトと他のオブジェクトの混合を宣言するとスペースを浪費する可能性があります。
Q:プログラムは、宣言する「char」ごとに4バイトを割り当てますか?
A:いいえ-絶対にありません;)
Q:1バイトを割り当てると、プログラムが余分なバイトを「埋める」可能性はありますか?
A:はい-絶対にそうです。
問題は「アライメント」です。一部のコンピュータアーキテクチャは、特定のオフセット(16ビット、32ビットなど)に関してデータ値にアクセスする必要があります。他のアーキテクチャは、オフセットに関して常に1バイトにアクセスする方がパフォーマンスが向上します。したがって、「パディング」:
char
実際、単一の変数を宣言しても意味がない場合があります。
char
ただし、-arrayが必要な理由はたくさんあるかもしれませんが、-arrayでは実際int
にはうまくいきません。
(データ構造をintで埋めてみてください...)
他の人はほとんどの場合これに答えています。charが1バイトであると仮定すると、charを宣言することは、それが常にアライメントにパディングすることを意味しますか?いいえ、一部のコンパイラはデフォルトで実行しますが、実行しないコンパイラもあります。多くの場合、どこかで何らかのコマンドを使用してデフォルトを変更できます。これは、charを使用すべきではないという意味ですか?場合によっては、最初にパディングが常に発生するとは限らないため、無駄なバイトが常に発生するとは限りません。コンパイラを使用して高級言語でプログラミングしているので、バイナリ全体で無駄なバイトが3つしかない場合は、もう一度考えてみてください。charを使用するアーキテクチャによっては、ある程度の節約になる可能性があります。たとえば、immediateをロードすると、一部のアーキテクチャでは3バイト以上節約できます。レジスタを使用して単純な操作を行うだけの他のアーキテクチャでは、バイトサイズのレジスタのように動作するように、より大きなレジスタを符号拡張またはクリップするための追加の命令が必要です。32ビットコンピューターを使用していて、1から100までしか数えないために8ビット文字を使用している場合は、フルサイズのintを使用することをお勧めします。長期的には、 char。これが8086ベースのPCでdosを実行している場合、それは別の話です。または、8ビットマイクロコントローラーの場合は、可能な限り8ビット変数に傾倒する必要があります。これが8086ベースのPCでdosを実行している場合、それは別の話です。または、8ビットマイクロコントローラーの場合は、可能な限り8ビット変数に傾倒する必要があります。これが8086ベースのPCでdosを実行している場合、それは別の話です。または、8ビットマイクロコントローラーの場合は、可能な限り8ビット変数に傾倒する必要があります。