在 C 中:我可以有两个不同类型的指针指向同一个地址吗?
In C: Can I have two pointers of different types pointing to the same address?
问题:
我可以让两个不同类型的指针(uint32_t *
和 char *
)指向同一个地址吗?
这就是我想要这个的原因:
我想在 C
中转换 UTF-8 to UTF-32,反之亦然。
比方说,我有一个 uint32_t
类型的变量,其中包含一个 UTF-32 编码的 unicode 字符。而且我已经知道它在以 UTF-8 编码时需要 4 个字节。它的二进制表示是这样的:
00000000000aaabbbbbbccccccdddddd
a、b、c、d 是 4 个不同的范围,每个位可以是 0 或 1。
通过巧妙的按位 &
、|
和 <<
操作,我可以重新排列这些位,以便在最后有这个新分布:
00000aaa00bbbbbb00cccccc00dddddd
然后我可以翻转一些位(再次使用 |
),得到这个
11110aaa10bbbbbb10cccccc10dddddd
当我将其拆分为数组中的 4 个后续 char
变量时,我得到了:
11110aaa 10bbbbbb 10cccccc 10dddddd
这正是同一个unicode字符的UTF-8编码。
因此,内存中相同的 4 个字节应该是一个 uint32_t
变量,同时也是一个包含 4 个 char
变量的数组:
所以,我想要这个:
uint32_t *utf32;
char utf8[4];
*utf32
是指向单个 4 字节长 uint32_t
变量的指针。
utf8
是指向 4 个 char
元素数组的指针,每个元素长 1 个字节。
而且我希望两个指针都指向同一个地址。所以我可以将一个 utf32 编码的字符写入变量 utf32
,就地转换它,然后从数组 utf32
中读取结果。这可能吗?如果是这样:我该怎么做?
(我在上个世纪用COBOL编码的时候经常用到这个技巧,因为在COBOL中很容易用很多不同的定义重载内存中的同一个区域。但我不知道该怎么做它在 C.)
我发现很多问题涉及指向同一地址的 2 个指针,但在这些问题中,指针始终具有相同的类型。还有一些其他问题是关于如果用某种类型定义的指针指向用另一种类型定义的地址时为什么会出错。但是我没有找到关于共享相同地址的两个不同类型的指针。
Can I have two pointers of different types (uint32_t * and char *) pointing to the very same address?
是的,你可以。
union U {
uint32_t ui32;
char c[4];
};
union U u;
u.ui32 = ...
uint32_t *pi = &u.ui32;
char *cp = u.c;
assert(pi == cp);
有一些 C 语言规则,如果您使用生成的 char*
执行除复制数据或复制数据之外的其他操作,但“指向同一地址的两个不同指针类型" 本身不是问题。
您也可以简单地将地址转换为所需的类型:
uint32_t x;
uint32_t *ip = &x;
char *cp = (char*)&x;
assert(ip == cp);
是的,两个不同类型的指针可以指向同一个地址
假设你记忆中的某处是这个 utf32,你知道它在哪里,所以我将其称为 address
。
所以如果你想把这 4 个字节当作 uint32
你可以这样做:
uint32_t* utf32 = address;
您可以轻松地将 is 视为字符数组:
char* utf8 = address;
如果您随后想要访问一个字符,您只需执行以下操作:
utf8[index]
问题:
我可以让两个不同类型的指针(uint32_t *
和 char *
)指向同一个地址吗?
这就是我想要这个的原因:
我想在 C
中转换 UTF-8 to UTF-32,反之亦然。
比方说,我有一个 uint32_t
类型的变量,其中包含一个 UTF-32 编码的 unicode 字符。而且我已经知道它在以 UTF-8 编码时需要 4 个字节。它的二进制表示是这样的:
00000000000aaabbbbbbccccccdddddd
a、b、c、d 是 4 个不同的范围,每个位可以是 0 或 1。
通过巧妙的按位 &
、|
和 <<
操作,我可以重新排列这些位,以便在最后有这个新分布:
00000aaa00bbbbbb00cccccc00dddddd
然后我可以翻转一些位(再次使用 |
),得到这个
11110aaa10bbbbbb10cccccc10dddddd
当我将其拆分为数组中的 4 个后续 char
变量时,我得到了:
11110aaa 10bbbbbb 10cccccc 10dddddd
这正是同一个unicode字符的UTF-8编码。
因此,内存中相同的 4 个字节应该是一个 uint32_t
变量,同时也是一个包含 4 个 char
变量的数组:
所以,我想要这个:
uint32_t *utf32;
char utf8[4];
*utf32
是指向单个 4 字节长uint32_t
变量的指针。utf8
是指向 4 个char
元素数组的指针,每个元素长 1 个字节。
而且我希望两个指针都指向同一个地址。所以我可以将一个 utf32 编码的字符写入变量 utf32
,就地转换它,然后从数组 utf32
中读取结果。这可能吗?如果是这样:我该怎么做?
(我在上个世纪用COBOL编码的时候经常用到这个技巧,因为在COBOL中很容易用很多不同的定义重载内存中的同一个区域。但我不知道该怎么做它在 C.)
我发现很多问题涉及指向同一地址的 2 个指针,但在这些问题中,指针始终具有相同的类型。还有一些其他问题是关于如果用某种类型定义的指针指向用另一种类型定义的地址时为什么会出错。但是我没有找到关于共享相同地址的两个不同类型的指针。
Can I have two pointers of different types (uint32_t * and char *) pointing to the very same address?
是的,你可以。
union U {
uint32_t ui32;
char c[4];
};
union U u;
u.ui32 = ...
uint32_t *pi = &u.ui32;
char *cp = u.c;
assert(pi == cp);
有一些 C 语言规则,如果您使用生成的 char*
执行除复制数据或复制数据之外的其他操作,但“指向同一地址的两个不同指针类型" 本身不是问题。
您也可以简单地将地址转换为所需的类型:
uint32_t x;
uint32_t *ip = &x;
char *cp = (char*)&x;
assert(ip == cp);
是的,两个不同类型的指针可以指向同一个地址
假设你记忆中的某处是这个 utf32,你知道它在哪里,所以我将其称为 address
。
所以如果你想把这 4 个字节当作 uint32
你可以这样做:
uint32_t* utf32 = address;
您可以轻松地将 is 视为字符数组:
char* utf8 = address;
如果您随后想要访问一个字符,您只需执行以下操作:
utf8[index]