bool型戻り値関数、return文を書かなかったときに何を返しますか?
2405 ワード
今日は1つのreturn文を書き落としたため、g++はまたwarningを開いていないで、結局悲劇になって、呼び出す時変な現象が現れて、そこで結局returnを書いていない時何を返すかをテストしました.
インスタンス:
プログラム出力:
5 0 0 4 1 1 0 64 true false true false
複数回の実行時に上の0、1を除く数字はランダムです.
さらにif文の判断から,返す文のない関数を直接判断するとbool変数の特性がなくなっていることがわかる.
さらにtrue、falseとの比較では彼らは設立されています.このときif else構造をうっかり使ってしまったとき、elseの文には永遠にifしか実行されません.
したがってboolが値を返す関数は、戻り文を書かない場合、デフォルトでtrueとfalseを返すのではなく、無定義の動作であり、後の判断エラーを引き起こす.
それはいったいどのようにしてこのような論理的でない現象が現れたのか、実験を続けてその奥義を垣間見てみましょう.
その過程を知るには,まずg++−Sを用いてこのコードのアセンブリコードをコンパイルしてみる.
全体のアセンブリコードが長すぎるとすべて貼り付けられず、if文(最初のif文と2番目)のアセンブリに注目します.
以上の解析から分かるように,プログラムが戻り文を書かなかった場合,その戻り値に行くと,この値が元の戻り値レジスタ(eax)にすでに存在する値であり,これは不確定である.例えば、ここで0,1でない数字を返した場合、次にbool判断を行う場合、1と異なっても0と異なっても、変更レジスタを0にしないので、対応するtest文は常に成立します.
ポインタを使用してbool変数の値を変更しても、上記のような効果が得られます.私たちが直接数字で比較したとき、この効果はありませんでした.プログラムが比較する前に隠れたタイプ変換をするからです.
添付exa,ax,ah,alレジスタの紹介:
まず図を見てください.図が読めば、この疑問を基本的に解決します.00000000 00000000 00000000 00000000|=========================================================================================================1文字|==AH===|--------8個0,1バイト|==AL=|---8個0,1バイトEAXは32ビットの送信器であるが、実は従来の8086 CPUのレジスタAXに2倍のデータビット数を増やしただけである.EAXとAXは独立することは不可能であり、両者は全体と部分の関係である.EAXに直接値を割り当てると、16ビット低い値を変更するとAX値が自然に変化し、AXはEAX全体に影響を与えることができます.AH,ALレジスタとAXの関係も同様である.
インスタンス:
#include
#include
using namespace std;
bool func()
{
int i=10;
i++;
}
int main()
{
bool a = func();
bool b=true;
bool c=100;
cout<
プログラム出力:
5 0 0 4 1 1 0 64 true false true false
複数回の実行時に上の0、1を除く数字はランダムです.
さらにif文の判断から,返す文のない関数を直接判断するとbool変数の特性がなくなっていることがわかる.
さらにtrue、falseとの比較では彼らは設立されています.このときif else構造をうっかり使ってしまったとき、elseの文には永遠にifしか実行されません.
したがってboolが値を返す関数は、戻り文を書かない場合、デフォルトでtrueとfalseを返すのではなく、無定義の動作であり、後の判断エラーを引き起こす.
それはいったいどのようにしてこのような論理的でない現象が現れたのか、実験を続けてその奥義を垣間見てみましょう.
その過程を知るには,まずg++−Sを用いてこのコードのアセンブリコードをコンパイルしてみる.
全体のアセンブリコードが長すぎるとすべて貼り付けられず、if文(最初のif文と2番目)のアセンブリに注目します.
.L7: // if
call _Z4funcv // func
xorl $1, %eax // %eax 1
testb %al, %al // al 0, test and, ZF; al eax 。
je .L8 // ZF 。
movl $.LC0, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
.L8: // if , 1 , 0 , , 。
call _Z4funcv
testb %al, %al
je .L9
movl $.LC0, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
以上の解析から分かるように,プログラムが戻り文を書かなかった場合,その戻り値に行くと,この値が元の戻り値レジスタ(eax)にすでに存在する値であり,これは不確定である.例えば、ここで0,1でない数字を返した場合、次にbool判断を行う場合、1と異なっても0と異なっても、変更レジスタを0にしないので、対応するtest文は常に成立します.
ポインタを使用してbool変数の値を変更しても、上記のような効果が得られます.私たちが直接数字で比較したとき、この効果はありませんでした.プログラムが比較する前に隠れたタイプ変換をするからです.
添付exa,ax,ah,alレジスタの紹介:
まず図を見てください.図が読めば、この疑問を基本的に解決します.00000000 00000000 00000000 00000000|=========================================================================================================1文字|==AH===|--------8個0,1バイト|==AL=|---8個0,1バイトEAXは32ビットの送信器であるが、実は従来の8086 CPUのレジスタAXに2倍のデータビット数を増やしただけである.EAXとAXは独立することは不可能であり、両者は全体と部分の関係である.EAXに直接値を割り当てると、16ビット低い値を変更するとAX値が自然に変化し、AXはEAX全体に影響を与えることができます.AH,ALレジスタとAXの関係も同様である.