void* 与 char* 具有相同的表示和内存对齐是什么意思?
What does it mean that void* has the same representation and memory alignment as char*?
我一直在阅读一些关于 void*
类型指针的文章,并从标准中找到了这个要求。
6.2.5.27:
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.39) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements.
我看到标准不保证所有指针类型都具有相同的长度,所以这里的底线是 void*
指针具有与 char*
相同的长度和对齐规则,对吧?
我不明白的是脚注 39),它说
The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
我的问题是:
“互换性”是什么意思?它是否表示函数 void* Func(void*)
的参数和 return 值都可以是 char*
?
如果是,是否是编译器隐式转换?
工会会员是怎么回事?我真的不明白这句话的意思。谁能给我一个简单的例子吗?
在 C 中,任何数据指针都可以传递给需要 void *
的函数,并且 void *
可以存储到任何指针类型。 void *
和其他指针类型之间存在隐式转换。但这并不意味着这种转换是无害的。在某些 void *
和 int *
具有不同表示的体系结构上,从 int *
转换为 void *
然后返回 int *
被指定为生成相同的指针值,但反过来不成立:将 void *
转换为 int *
并返回 void *
可能会产生不同的值,特别是如果 void *
不是通过转换 int *
.
互换性意味着这种隐式转换不会改变指针的表示形式。转换可以通过两种方式成功进行:将字符指针转换为 void *
并返回生成相同的指针,反之亦然。
这是一个例子:
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main() {
char *s = "abc";
char *s1;
void *p;
void *p1;
assert(sizeof(p) == sizeof(s));
memcpy(&p, &s, sizeof(p));
p1 = s;
assert(p == p1);
memcpy(&s1, &p1, sizeof(s1));
assert(s == s1);
return 0;
}
但是请注意,这并不意味着 !memcmp(&p1, &s, sizeof(p1))
因为指针可以有填充位。您也不能通过 void *
:
强制转换来违反严格的别名规则
float f = 1.0; unsigned int i = *(int *)(void *)&f'
不正确。
float f = 1.0; unsigned int i; memcpy(&i, &f, sizeof(i));
如果 sizeof(int) == sizeof(float)
正确,但可能会产生陷阱值。
指针只是内存中的一个地址。你可以认为内存是一个字节的连续区域,它非常大(例如,在 32 位进程上它将是 4 GB,但通常进程不能使用整个取决于系统)。
这意味着指针的值实际上是一个整数,表示内存中字节的从零开始的索引(例如,值为 0
的指针指的是内存中的第一个字节,但实际上你将无法取消引用该地址,因为它是空指针)。
当您取消对指针的引用时,它所做的是 reading/writing 指向该地址。 read/write 的大小取决于指针的类型。如果指针是 int
并且它在该系统上的大小是 32 位,即 4 个字节;它将 read/write 4 个字节从该地址开始。对齐意味着值如何存储在内存中。假设存储在内存中的值需要是 16 字节对齐,这意味着它的起始地址必须乘以 16.
我这里讲解的只是指针的高阶,入门应该够用了。实际上它有很多与之相关的东西,比如内存保护、分页等。
我一直在阅读一些关于 void*
类型指针的文章,并从标准中找到了这个要求。
6.2.5.27:
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.39) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements.
我看到标准不保证所有指针类型都具有相同的长度,所以这里的底线是 void*
指针具有与 char*
相同的长度和对齐规则,对吧?
我不明白的是脚注 39),它说
The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
我的问题是:
“互换性”是什么意思?它是否表示函数
void* Func(void*)
的参数和 return 值都可以是char*
?如果是,是否是编译器隐式转换?
工会会员是怎么回事?我真的不明白这句话的意思。谁能给我一个简单的例子吗?
在 C 中,任何数据指针都可以传递给需要 void *
的函数,并且 void *
可以存储到任何指针类型。 void *
和其他指针类型之间存在隐式转换。但这并不意味着这种转换是无害的。在某些 void *
和 int *
具有不同表示的体系结构上,从 int *
转换为 void *
然后返回 int *
被指定为生成相同的指针值,但反过来不成立:将 void *
转换为 int *
并返回 void *
可能会产生不同的值,特别是如果 void *
不是通过转换 int *
.
互换性意味着这种隐式转换不会改变指针的表示形式。转换可以通过两种方式成功进行:将字符指针转换为 void *
并返回生成相同的指针,反之亦然。
这是一个例子:
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main() {
char *s = "abc";
char *s1;
void *p;
void *p1;
assert(sizeof(p) == sizeof(s));
memcpy(&p, &s, sizeof(p));
p1 = s;
assert(p == p1);
memcpy(&s1, &p1, sizeof(s1));
assert(s == s1);
return 0;
}
但是请注意,这并不意味着 !memcmp(&p1, &s, sizeof(p1))
因为指针可以有填充位。您也不能通过 void *
:
float f = 1.0; unsigned int i = *(int *)(void *)&f'
不正确。float f = 1.0; unsigned int i; memcpy(&i, &f, sizeof(i));
如果sizeof(int) == sizeof(float)
正确,但可能会产生陷阱值。
指针只是内存中的一个地址。你可以认为内存是一个字节的连续区域,它非常大(例如,在 32 位进程上它将是 4 GB,但通常进程不能使用整个取决于系统)。
这意味着指针的值实际上是一个整数,表示内存中字节的从零开始的索引(例如,值为 0
的指针指的是内存中的第一个字节,但实际上你将无法取消引用该地址,因为它是空指针)。
当您取消对指针的引用时,它所做的是 reading/writing 指向该地址。 read/write 的大小取决于指针的类型。如果指针是 int
并且它在该系统上的大小是 32 位,即 4 个字节;它将 read/write 4 个字节从该地址开始。对齐意味着值如何存储在内存中。假设存储在内存中的值需要是 16 字节对齐,这意味着它的起始地址必须乘以 16.
我这里讲解的只是指针的高阶,入门应该够用了。实际上它有很多与之相关的东西,比如内存保护、分页等。