2016-03-28 10 views
3

uintmax_tは、関数ポインタを保持するのに十分な大きさであることを保証していますか?(u)intmax_tは関数ポインタを保持できますか?

私はこの知っている:

uintmax_t 

:次のタイプは、任意の符号なし整数型のいずれかの値を表す 可能な符号なし整数型を指定

を以下の型は、を持つ符号なし整数型を指定します。任意の有効なポインタがこの型に変換することができる無効にするプロパティは、 は次にvoidへのポインタに変換し、その結果、元のポインタに等しい を比較する:

いるuintptr_tとボイドポインタその関数ポインタを保持するのに十分な大きさでないかもしれないので、uintptr_tは関数ポインタを保持するのに十分な大きさでないかもしれません。

+0

私はそれが十分な大きさでなければならないだろうと思うだろうが、私はドキュメントをサポートして見つけることができません。この質問は関連性があります:http://stackoverflow.com/questions/15823217/does-the-c-standard-guarantee-that-stduintmax-t-can-hold-all-values-of-std –

+1

標準がそうだとしたら、答えはノーだと思います。 (AFAIKでは、標準では関数ポインタで変換/ワッキーを行うことはできません) –

+0

関数ポインタを整数またはオブジェクトポインタに変換することは、未定義の動作です。これには 'void * 'が含まれます。 – Olaf

答えて

4

いいえ、一般的ではありません。 void*そして結果として[u]intptr_tは、オブジェクトポインタを保持するのに十分な幅であることが保証されています。これはオブジェクト型へのポインタです。関数ポインタは、いくつかのプラットフォームでは、関数のエントリポイントよりも幅が広く、より多くの情報を含んでいます。したがって、そのようなプラットフォームでは、またはuintptr_tは、必要とされるすべての情報を表すのに十分なビットがありません。

多くのプラットフォームでは、関数ポインタはオブジェクトポインタと同じ幅を持ちますが、複数のプラットフォーム間で変換することもできます。しかし、これはC標準の拡張であり、プラットフォームのドキュメントを調べる必要があります。

4

Cのような保証はありません。

最初に、NULLポインタを除いて、ポインタが無損失で整数型に変換されるという保証はありません。 uintptr_tは、無駄にvoidポインタ(したがって、すべてのonjectポインタ)を表すことができる必要があります。ただし、実装がuintptr_tであるという保証はなく、intptr_tはオプションです(最後の文は§ 7.20.1.4)。

第2に、関数ポインタはオブジェクトポインタではなく、必ず1つをvoidポインタに変換して戻すことはできません。だからuintptr_tが存在しても、関数ポインタを保持するのに十分な大きさではないかもしれません。

XSI(XSI/XSI)互換の実装(ほとんどのPosixシステム)では、voidポインタと関数ポインタを変換できる必要があり、uintptr_tが存在する必要があります。その場合、あなたは保証をしています。 (ボイドと関数ポインタ間の兌換を発行7(2008)でのPosixをベースにXSIから移動されたdlsymシステムインターフェースによって必要とされる。しかしながら、uintptr_tをの存在はXSI拡張であり続けている。)

1

uintmax_tの保証は、関数ポインタを保持するのに十分な大きさですか?

他人からの返答も保証されません。


しかし、関数ポインタのサイズが存在し、ビットパターンを持っています。十分に大きければ、uintmax_tはポインタのビットパターンを保持することができます(さらに多分)。このサイズテストは、コンパイル時に評価することができます。

#include <assert.h> 
#include <stdio.h> 
#include <stdint.h> 

int foo(int x) { 
return x+x; 
} 

int main(void) { 
    union { 
    uintmax_t um; 
    int (*fp)(int); 
    } u = {0}; 
    assert(sizeof u.um >= sizeof u.fp); // This assertion may fail 
    u.fp = foo; 

    uintmax_t save = u.um; 
    printf("%ju\n", save); 

    u.um = save; 
    printf("%d\n", (*u.fp)(42)); 

    return 0; 
} 

出力

4198816 
84 
関連する問題