web-dev-qa-db-ja.com

どうすればintからsize_tに安全に変換できますか?

GCCでintをsize_tに割り当てる(またはmallocで使用する)と、次の警告が生成されます。

警告:「int」から「size_t」に変換すると、結果の符号が変わる可能性があります[-Wsign-conversion]

これを解決するために、最初に変換が有効かどうかをチェックしてからキャストを実行する関数で変換をラップしたいと思います。

これは私がこれまでに持っているものです:

/* Convert int src to size_t dst. */
/* Assumes dst points to valid size_t address. */
int safe_size_t_from_int(size_t *dst, int src) {
    if(src < 0) return SAFE_ERROR_NEGATIVE;
    if(SIZE_MAX < INT_MAX) {
        if(src > (int)SIZE_MAX) return SAFE_ERROR_OVERFLOW;
    }
    *dst = (size_t)src;
    return SAFE_SUCCESS;
}

私は何かが足りませんか?すでに存在する安全な変換を備えたライブラリはありますか?

私が見つけることができる最も近いものは Microsoft Intsafe.h ですが、それはWin32タイプ専用のようです。

[〜#〜] edit [〜#〜]chuxのコメントに従って変更されました。

7
Martin

GCCでのコンパイラの警告を回避するには、単一のキャスト操作によって実行されるアクションを次のいずれかに制限します。

  1. 切り捨てまたは拡張
  2. 符号付きまたは符号なしを捨てる
  3. const-nessまたはnon-const-nessを捨てる

size_tは常に、voidポインタを保持するのに十分な大きさの符号なし型です。 intからsize_tへのキャストには、extendとsigned-nessのキャストアウェイという2つのキャスト操作が含まれます。

GCC 4.8.3でコンパイラ警告を生成しない( '-Wall -Werror -Wextra'を使用する)2つの関数を次に示します。それらは、追加の戻りパラメーターではなく、(番兵値を介して)インラインで失敗を返します。

int size_t2int(size_t val) {
    return (val <= INT_MAX) ? (int)((ssize_t)val) : -1;
}

size_t int2size_t(int val) {
    return (val < 0) ? __SIZE_MAX__ : (size_t)((unsigned)val);
}
5
dembones