文字列を一般的でない整数型に移植可能に変換する方法は?
質問
背景:たとえば、scanf()
に使用したい場合、uint16_t
などの文字列を標準整数型に変換するには、SCNu16
から<inttypes.h>
を使用します。 、このように:
#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);
しかし、pid_t
のようなより一般的でない整数型にはそのようなものはありません。 printf()
では通常の整数型のみがサポートされます。他の方法、つまり移植可能なintmax_t
をPRIdMAX
に変換するには、次のように<=>にキャストし、<=>を使用します。
#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);
ただし、移植可能な<=>を<=>に変換する方法はないようです。だからこれは私の質問です:これを移植可能にする方法は?
#include <stdio.h>
#include <sys/types.h>
pid_t x;
char *xs = 17;
sscanf(xs, "%u", &x); /* Not portable! pid_t might not be int! /*
<=>に<=>して、<=>にキャストする前に値が<=> <!>#8217; sの制限内にあることを確認しようと考えましたが、方法はないようです<=>の最大値または最小値を取得します。
解決
堅牢でポータブルなソリューションが1つあります。これは、strtoimax()
を使用してオーバーフローをチェックすることです。
つまり、intmax_t
を解析し、pid_t
からのエラーをチェックし、<!> quot; fits <!> quot;かどうかも確認します。 scanf()
にキャストして、元のstrtoll()
値と比較します。
#include <inttypes.h>
#include <stdio.h>
#include <iso646.h>
#include <sys/types.h>
char *xs = "17"; /* The string to convert */
intmax_t xmax;
char *tmp;
pid_t x; /* Target variable */
errno = 0;
xmax = strtoimax(xs, &tmp, 10);
if(errno != 0 or tmp == xs or *tmp != '\0'
or xmax != (pid_t)xmax){
fprintf(stderr, "Bad PID!\n");
} else {
x = (pid_t)xmax;
...
}
<=>を使用することはできません。なぜなら、(コメントで述べたように) <=>はオーバーフローを検出しないからです。しかし、<=>に関連する関数はいずれも<=>をとらないと言って間違えました。 <=>は!
また、整数型のサイズ(この場合は<=>)がわからない限り、<=>以外のものを使用することもできません。
他のヒント
あなたがどの程度ポータブルになりたいかによって異なります。 POSIXによれば、pid_t
はプロセスIDとプロセスグループIDを格納するために使用される符号付き整数型です。実際には、安全にlong
が十分に大きいと想定できます。それに失敗すると、intmax_t
は十分に大きくなければなりません(したがって、有効な<inttypes.h>
を受け入れます)。問題は、そのタイプが<unistd.h>
で正当でない値を受け入れる可能性があることです。あなたは岩と難しい場所の間で立ち往生しています。
<sys/types.h>
を使用しますが、100年のソフトウェア考古学者が見つけて観察する不明瞭なコメントを除いて、それについてあまり心配しません。256ビットCPUが渡されたときに停止する理由がわかります<=>。
POSIX 1003.1-2008 がWebで利用可能になりました(すべて3872そのページ、PDFおよびHTML)。登録する必要があります(無料)。 Open Group Bookstore からアクセスしました。
そこにあるのは、符号付き整数型でなければならないということだけです。明らかに、すべての有効な符号付き整数値は<=>に収まります。 PID_T_MAXまたはPID_T_MINまたは他のそのような値を示す<=>または<=>の情報が見つかりません(ただし、今夜だけアクセスできるので、探していない場所に隠れている可能性があります) 。 OTOH、私は元のコメントに賛成です-32ビットの値は実用的には十分だと思います。とにかく<=>を使用します。これは8ビットのマシンでは64ビットになります。発生する可能性のある最悪の最悪の事態は、「適切に特権を与えられた」プロセスが大きすぎる値を読み取り、型の不一致のために間違ったプロセスに信号を送信したことだと思います。私はそれについて心配するだろうとは思いません。
<=> の下の... oooh!... p400
実装は、幅が blksize_t、pid_t、size_t、ssize_t、およびsuseconds_tの長さは、long型の幅以下です。
本当に心配な場合は、_assert(sizeof(pid_t) <= long)
または '%'に選択するタイプを選択できます。
で説明されているとおりこの答え、仕様にはsigned int
と書かれています。 「int」が変更されると、定義により「%u」も変更されます。