exit()ステータスで256で除算するよりもCでWEXITSTATUSマクロを使用する利点はありますか?
-
03-07-2019 - |
質問
大学でエクササイズをしていたときに、出口で値を返す必要がありました。その値は実際には何かの数でした。これは255(exit()で処理できない)を超える可能性がありますが、教師はカウントがその値を超えないテストデータを使用することを提案しました。
このすべての後、このカウント値、終了ステータスを処理する必要がありました。メインプロセスでwaitpid()を使用してこの値を取得しました。驚いたことに、子プロセスが1を返した場合、「本当の」メインプロセスの値は256、2は512などでした...
この値を印刷する必要があったので、単純に256で割って完了しました。ただし、WEXITSTATUS()マクロを使用すると、この値も思いのままに取得できます...
Cソースコードを調べたところ、次のことがわかりました。
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
ここで何が起こっているかを理解しています。たとえば、バイナリの512は10 0000 0000で、8を右にシフトすると00 0000 0010になります。これは10進数で2です。このマクロで理解できないのは、&演算子と0xff00が乱数のように見えるという事実(おそらくそうではありませんが、どこから来たのでしょうか?)。これが正確に何をするのか、なぜ"& 0xff00"マクロで?うまくいかないでしょうか?
このトピックの本当の質問は、コードでこのマクロを呼び出すことと256で除算することと同じですか?
解決
このトピックの本当の質問は、 このマクロを呼び出すのと同じことです 私のコードでは256で除算していますか?
おそらく、子プロセスが正常に終了する場合(つまり、セグメンテーション障害、アサーション障害などではなく、exit()を呼び出すことで)常に動作します。
waitpid()
によって保存されるステータスは、子プロセスが終了した理由と終了コードの両方をエンコードします。理由は最下位バイト( status& 0xff
で取得)に保存され、終了コードは次のバイト( status& 0xff00
でマスクされます)に保存されます WEXITSTATUS()
)によって抽出されます。プロセスが正常に終了した場合、理由は0であるため、 WEXITSTATUS
は8でシフト(または256で除算)するのと同じです。ただし、プロセスがシグナル(SIGSEGVなど)によって強制終了された場合、終了コードはないため、 WTERMSIG
を使用して、理由バイトからシグナル番号を抽出する必要があります。
他のヒント
ステータス変数がマシン上の符号付き16ビット整数(「short」)で、「int」が32ビット量で、終了ステータスが128..255の範囲にある場合、WEXITSTATUS ()でも正しい値が得られますが、256で除算するか、単に右にシフトすると間違った値になります。
これは、ショートが32ビットに符号拡張され、マスキングにより符号拡張が取り消され、結果に正しい(正の)値が残るためです。
マシンが16ビット整数を使用している場合、WEXITSTATUS()のコードはおそらく同様の動作を保証するためにシフトしてからマスクします:
#define WEXITSTATUS(status) (((status)>>8) & 0xFF)
WEXITSTATUS()マクロを使用する必要があるのは、実装がそのような詳細を処理するためです。
単一のUnix仕様の確認からわかる限り、あなたのシステムはたまたま右端から2番目のオクテットに終了ステータスを格納しますが、標準はそうです。したがって、少なくともいくつかの理由でマクロを使用する必要があります。
- それらは正しいです。負の数をビットシフトすると、プラットフォームによって異なることが行われます。あなたが望むように動作しますか?わからない。
- これらはシンプルです。
WEXITSTATUS
の機能がすぐにわかります。他のアプローチではそうではありません。WIFSIGNALED
の手巻きバージョンを見た場合、それを認識しますか?WIFSIGNALED
よりも長くかかります。 - これらはポータブルです。仕様がそのように指示しているため、すべてのシステム(少なくともほとんどすべてのUnixライクなシステム)で動作します。
ここで0xff00はバイナリマスクです(リンクテキスト)。値とANDすると、2番目のバイト(右からカウント)を除くすべてのビットがゼロに設定されます。
WEXITSTATUS
は、正常に終了したことがわかっているプロセスでのみ使用してください。この情報は、 WIFEXITED
マクロによって提供されます。
このトピックの本当の質問は、コードでこのマクロを呼び出すことと256で除算することと同じですか?
このマクロによりコードが読みやすくなり、Posix準拠の実装で動作することが保証されます。私の知る限り、Posixはステータスの形式を指定していないため、コードがどこでも機能することは期待できません。