ポインタから整数への変換、整数からポインタへの変換
ポインタから整数への変換(pointer to integer)
整数からポインタへの変換(integer to pointer)
ポインタ値を整数として扱いたいときの正しい方法について?
型はstdint.hに定義されている下記を使う
intptr_tは符号付き整数型
uintptr_tは符号無し整数型
そもそもなぜintptr_tやuintptr_tが定義されているかは、intやlongは32bit、64bit環境などのアーキテクチャによって型のサイズが変わってしまうので移植性を高めるためにこういう独自の型が出てきた(はず)
printfで書式を指定する場合、inttypes.hをインクルードしてPRIdPTRとかPRIuPTRを使う
PRI<出力フォーマット><型>
より詳しい説明は↓を見る
INT36-C. ポインタから整数への変換、整数からポインタへの変換
code:pointerIntConv.c
#include <stdio.h>
#include <stddef.h> // ptrdiff_t
#include <stdint.h> // intptr_t, uintptr_t
#include <inttypes.h> // PRIdPTR, PRIuPTR
#define PRINTLN(fmt, x) printf("%s = " fmt "\n",#x,(x))
// 要素の
void demo_pointer_diff_elems(void) {
int arr10 = {0};
int *p1 = &arr2;
int *p2 = &arr7;
ptrdiff_t diff_elems = p2 - p1;
printf("pointer diff elems\n");
printf(" diff_elems = %td\n", diff_elems);
}
void demo_pointer_diff_bytes(void) {
int arr10 = {0};
int *p1 = &arr2;
int *p2 = &arr7;
uintptr_t diff_bytes = (uintptr_t)p2 - (uintptr_t)p1;
// バイト数 / 配列要素の型サイズで
uintptr_t diff_elems = diff_bytes / sizeof(arr0);
printf("pointer diff bytes\n");
printf(" diff_bytes = %" PRIuPTR "\n", diff_bytes);
printf(" ");
PRINTLN("%zd" , sizeof(arr0));
printf(" diff_elems = %" PRIuPTR "\n", diff_elems);
}
int main() {
int x = 10;
// ポインタ変数
int *p;
// xのアドレスを代入
p = &x;
// pの参照先のxの値を書き換える
*p = 15;
intptr_t ptrVal = (intptr_t)p;
printf("x = %d\n", x);
// %pでアドレスを16進数で表示
printf("&x = %p\n", &x);
printf("p = %p\n", p);
// PRI<出力フォーマット><型>
printf("ptrVal = %" PRIdPTR "\n", ptrVal);
printf("*p = %d\n", *p);
printf("&p = %p\n", &p);
// intptr_t をポインタに戻す
int *p2 = (int *)ptrVal;
printf("p2 = %d\n", *p2);
demo_pointer_diff_elems();
demo_pointer_diff_bytes();
}
code:memo
$ curl -O https://scrapbox.io/api/code/pogi-log/%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E3%81%8B%E3%82%89%E6%95%B4%E6%95%B0%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B%E3%80%81%E6%95%B4%E6%95%B0%E3%81%8B%E3%82%89%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B/pointerIntConv.c && gcc -Wall -Wextra -Wconversion -Wsign-conversion pointerIntConv.c && ./a.out
code:memo
x = 15
&x = 0x7fff30d89b1c
p = 0x7fff30d89b1c
ptrVal = 140734012889884
*p = 15
&p = 0x7fff30d89b20
p2 = 15
pointer diff elems
diff_elems = 5
pointer diff bytes
diff_bytes = 20
sizeof(arr0) = 4
diff_elems = 5
intptr_t, uintptr_tの記述
7.18.1.4 Integer types capable of holding object pointers
1 The following type designates a signed integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
uintptr_t
These types are optional.
ref: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
↓
7.18.1.4 オブジェクトポインタを保持できる整数型
1 以下の型は、voidへの有効なポインタをこの型に変換し、voidへのポインタに戻すことができ、その結果は元のポインタと等しく比較されるという特性を持つ符号付き整数型を指定します:
intptr_t
次の型は符号なし整数型で、voidへの有効なポインタをこの型に変換し、voidへのポインタに戻すことができ、その結果は元のポインタと等しく比較されるという特性を持つ:
uintptr_t
これらの型はオプションである。
確認用
Q. ポインタから整数への変換
Q. 整数からポインタへの変換
Q. なぜintptr_t、uintptr_tが定義されているか
関連
ptrdiff_t
ILP64
タグ付きポインタ
参考
2016年、C言語はどう書くべきか (後編) | POSTD
メモ
ポインタをint型にキャストするな! | 株式会社クローバーフィールド
avr-libc: <inttypes.h>: 整数型変換
C言語/標準ライブラリ/inttypes.h - Wikibooks
調査用
Google.icon ポインタから整数への変換(日)
Google.icon 整数からポインタへの変換(日)
Google.icon Pointer to integer(英)