1

配列のアドレスを変数に入れるにはどうすればよいですか?

char * str1 = "Hello";
int add = 0;

次に、配列のアドレスをに入れたいと思いますadd。次の方法で配列のアドレスを出力できることはわかっています。

printf("Address = %p", str1);

しかし、アドレスを変数に格納したいと思います。

4

4 に答える 4

4

メモリアドレスを変数に格納する場合、正しい方法は変数をstd::intptr_tまたはとして入力することですstd::uintptr_t。これは、これらのタイプが任意のメモリアドレスを保持するのに十分な大きさであることが保証されているためです。

char * str1 = "Hello";
uintptr_t p = (uintptr_t)str1;

それとは別に、の値は(を指す)の値とは異なりstr1ますが、すでにメモリアドレス(を指す)であることに注意してください。H&str1str1

于 2012-06-20T09:10:51.763 に答える
3

ポインタを数値に変えるには、再解釈が必要です。

add = reinterpret_cast<int>(str1);

しかし、このアプローチに関連するあらゆる種類の問題があります。

  • sizeof(int)<sizeof(char *)の場合、ポインターの一部が失われ、それを復元することはできません。
  • 一部の最適化では、予期しないエイリアシングが原因でコードが無効になる場合があります。

ポインターまたは整数を保持できる変数が必要な場合は、代わりに共用体を使用することをお勧めします。

于 2012-06-20T09:11:54.867 に答える
1

ジョンの受け入れられた答えに対するあなたのコメントから:

char str1[] = "Hello";
char* str2 = &str1[0];
uintptr_t p = (uintptr_t)str2;
std::cout << std::hex << p << std::endl;
p = (uintptr_t)&str1[1];
std::cout << std::hex << p << std::endl;
p = (uintptr_t)&str1[0];
std::cout << std::hex << p << std::endl;

これは、ポインタ値を読み取り可能な形式でストリーミングできるようにすることが目的であることを意味します。標準では、これを実装定義の方法で次のように規定しています。

basic_ostream<charT,traits>& operator<<(const void* p);

したがって、おそらくあなたが本当に望んでいるのは、以下のC ++スタイルまたは(簡潔ですが、自己文書化およびコンパイラーチェックが少ない)Cスタイルのコードによって満たされます。

std::cout << static_cast<void*>(str1) << '\n';
std::cout << (void*)str1 << '\n';

(ただし、特に数値バージョンが必要な場合、または先頭に0xがない状態で16進数で表示されるようにする場合、または実装が決定する可能性のあるその他のものを使用する場合は、Jonの提案または独自の(コンパイル時にチェックされる)ロジックに戻ります。十分な大きさの整数型を見つけるために。

于 2012-06-20T09:55:55.467 に答える
1

使用reinterpret_cast(5.2.10 / p4を参照):

4ポインタは、それを保持するのに十分な大きさの任意の整数型に明示的に変換できます。マッピング関数は実装定義です。[注:基礎となるマシンのアドレス指定構造を知っている人にとっては驚くことではありません。—エンドノート]

static_assert( sizeof( unsigned int ) >= sizeof( &str1[ 0 ] ),  "warning: use a wider type!" );
unsigned int add = reinterpret_cast< unsigned int >( &str1[ 0 ] );
于 2012-06-20T09:12:03.367 に答える