この質問から得た回答から、C++ は、Cから算術演算を実行するときに を に変換するこの要件を継承しているようです。そもそもなぜこれが C に導入されたのか、あなたの頭脳を選んshort
でよろしいですか? これらの操作を として実行しないのはなぜですか?int
short
例(コメントのdypの提案から取得):
short s = 1, t = 2 ;
auto x = s + t ;
x
int型になります。
If we look at the Rationale for International Standard—Programming Languages—C in section 6.3.1.8
Usual arithmetic conversions it says (emphasis mine going forward):
The rules in the Standard for these conversions are slight modifications of those in K&R: the modifications accommodate the added types and the value preserving rules. Explicit license was added to perform calculations in a “wider” type than absolutely necessary, since this can sometimes produce smaller and faster code, not to mention the correct answer more often. Calculations can also be performed in a “narrower” type by the as if rule so long as the same end result is obtained. Explicit casting can always be used to obtain a value in a desired type
Section 6.3.1.8 from the draft C99 standard covers the Usual arithmetic conversions which is applied to operands of arithmetic expressions for example section 6.5.6 Additive operators says:
If both operands have arithmetic type, the usual arithmetic conversions are performed on them.
We find similar text in section 6.5.5 Multiplicative operators as well. In the case of a short operand, first the integer promotions are applied from section 6.3.1.1 Boolean, characters, and integers which says:
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.48) All other types are unchanged by the integer promotions.
The discussion from section 6.3.1.1
of the Rationale or International Standard—Programming Languages—C on integer promotions is actually more interesting, I am going to selectively quote b/c it is too long to fully quote:
Implementations fell into two major camps which may be characterized as unsigned preserving and value preserving.
[...]
The unsigned preserving approach calls for promoting the two smaller unsigned types to unsigned int. This is a simple rule, and yields a type which is independent of execution environment.
The value preserving approach calls for promoting those types to signed int if that type can properly represent all the values of the original type, and otherwise for promoting those types to unsigned int. Thus, if the execution environment represents short as something smaller than int, unsigned short becomes int; otherwise it becomes unsigned int.
This can have some rather unexpected results in some cases as Inconsistent behaviour of implicit conversion between unsigned and bigger signed types demonstrates, there are plenty more examples like that. Although in most cases this results in the operations working as expected.
これは言語の機能ではなく、コードが実行される物理プロセッサ アーキテクチャの制限です。Cのint
typer は通常、標準の CPU レジスタのサイズです。シリコンが増えると、より多くのスペースと電力が必要になるため、多くの場合、演算は「自然なサイズ」のデータ型でのみ実行できます。これは普遍的に当てはまるわけではありませんが、ほとんどのアーキテクチャにはまだこの制限があります。つまり、2 つの 8 ビット数を加算する場合、プロセッサで実際に行われるのは、単純なビット マスクまたは別の適切な型変換のいずれかが続く、ある種の 32 ビット演算です。
short
タイプは、char
標準的な「ストレージタイプ」、つまり、スペースを節約するために使用できるサブ範囲によって考慮されますが、サイズが CPU にとって「不自然」であるため、速度は得られません。
一部の CPU ではこれは当てはまりませんが、優れたコンパイラは、たとえば unsigned char に定数を追加し、その結果を unsigned char に格納する場合、unsigned char -> int
変換を行う必要がないことに気付くほど賢いです。たとえば、g++ の場合、内部ループ用に生成されたコード
void incbuf(unsigned char *buf, int size) {
for (int i=0; i<size; i++) {
buf[i] = buf[i] + 1;
}
}
ただです
.L3:
addb $1, (%rdi,%rax)
addq $1, %rax
cmpl %eax, %esi
jg .L3
.L1:
addb
unsigned char 加算命令 ( ) が使用されていることがわかります。
short int の間で計算を行い、結果を short int に格納する場合も同じことが起こります。
リンクされた質問はそれをかなりうまくカバーしているようです.CPUはそうではありません. 32 ビット CPU には、32 ビット レジスタ用に設定されたネイティブ算術演算があります。プロセッサは好みのサイズで動作することを好みます。このような操作では、小さい値をネイティブ サイズのレジスタにコピーする方が安上がりです。(x86 アーキテクチャの場合、32 ビット レジスタは、16 ビット レジスタの拡張バージョン ( eax
to ax
、ebx
tobx
など) であるかのように名前が付けられます。x86 整数命令を参照してください)。
一部の非常に一般的な演算、特にベクトル/浮動小数点演算では、異なるレジスタ タイプまたはサイズで動作する特殊な命令が存在する場合があります。短いようなものでは、(最大で) 16 ビットのゼロをパディングしても、パフォーマンス コストはほとんどなく、特殊な命令を追加することはおそらく時間やダイのスペースに見合う価値はありません (理由について本当に物理的に知りたい場合は、私は実際のスペースを取るかどうかはわかりませんが、より複雑になります)。