11

scanf()いくつかの背景: たとえば、文字列を のような標準の整数型に変換するために for を使用したい場合は、次のようにfromuint16_tを使用します。SCNu16<inttypes.h>

#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);

しかし、より珍しい整数型のようなpid_tものにはそのようなものはありません。では、通常の整数型のみがサポートされてい<inttypes.h>ます。printf()移植可能な aに別の方法で変換するには、次のように にpid_tキャストしてintmax_t使用できますPRIdMAX

#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);

scanf()ただし、 に移植可能にする方法はないようですpid_t。これが私の質問です:これを移植可能にするにはどうすればよいですか?

#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! /*

にキャストしてから、値がの制限内にあることを確認してから にキャストすることを考えscanf()ましたが、 の最大値または最小値を取得する方法はないようです。intmax_tpid_tpid_tpid_t

4

3 に答える 3

8

堅牢でポータブルなソリューションが 1 つあります。それはstrtoimax()、オーバーフローを使用してチェックすることです。

つまり、 を解析しintmax_t、 からのエラーをチェックし、キャストして元の値と比較することでstrtoimax()、 に「適合」するかどうかも確認します。pid_tintmax_t

#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;
  ...
}

scanf()(コメントで言ったように)scanf()オーバーフローを検出しないため、使用することはできません。strtoll()しかし、関連する関数はどれもintmax_t;を取らないと言ったのは間違っていました。strtoimax()します!

strtoimax()また、整数型 (pid_tこの場合は )のサイズがわかっている場合を除き、他のものを使用しても機能しません。

于 2009-02-12T19:18:10.550 に答える
3

それは、あなたがどれだけポータブルになりたいかによって異なります。POSIX によると、これpid_tはプロセス ID とプロセス グループ ID を格納するために使用される符号付き整数型です。実際には、安全性がlong十分に大きいと想定できます。それができない場合、あなたintmax_tは十分に大きくなければなりません(そのため、有効な をすべて受け入れますpid_t)。問題は、その型が で正当でない値を受け入れる可能性があることですpid_t。あなたは岩と固い場所の間に立ち往生しています。

long100年後のソフトウェア考古学者が見つけて観察するであろうどこかのあいまいなコメントを除いて、私はそれを使用し、あまり心配しません. pid_t。_

POSIX 1003.1-2008が Web で利用できるようになりました (3872 ページすべてが PDF と HTML で提供されます)。登録(無料)が必要です。Open Group Bookstoreから入手しました。

そこにあるのは、符号付き整数型でなければならないということだけです。明らかに、すべての有効な符号付き整数値は に収まりますintmax_t<inttypes.h>PID_T_MAX や PID_T_MIN などの値を示すorの情報を見つけることができません<unistd.h>(しかし、今晩しかアクセスできなかったので、探していない場所に隠されている可能性があります)。OTOH、私は元のコメントを支持します-32ビットの値が実用的に適切であると信じており、longとにかく使用します.8ビットマシンでは64ビットになります。起こりうる最悪の事態は、「適切に特権を与えられた」プロセスが大きすぎる値を読み取り、型の不一致のために間違ったプロセスにシグナルを送信したことだと思います。私はそれについて心配するだろうと確信していません。

...うおお!...p400 下<sys/types.h>

実装は、blksize_t、pid_t、size_t、ssize_t、および suseconds_t の幅が long 型の幅を超えない 1 つまたは複数のプログラミング環境をサポートする必要があります。

于 2009-01-13T02:54:33.073 に答える
0

あなたが本当に心配しているなら_assert(sizeof(pid_t) <= long)、あなたの「%」のもののためにあなたが選ぶことができるか、どんなタイプでもかまいません。

この回答で説明されているように、仕様にはsigned int. 「int」が変更された場合、定義による「%u」も変更されます。

于 2009-01-13T03:10:08.813 に答える