c - 在指针算术中使用 char* over void*
问题描述
我正在浏览此代码以用于学习目的,并对这一行有疑问:
return (char*)desc + sizeof *desc;
为什么要desc
投到char*
?我试图用我自己的代码来模仿它:
#include <stdio.h>
#include <stdlib.h>
struct Test {
int value;
};
int main() {
struct Test* test = malloc(sizeof test);
struct Test* test1 = (void*)test + sizeof *test;
test1->value = 1;
printf("%d\n", test1->value);
struct Test* test2 = (void*)test1 + sizeof *test;
test2->value = 10;
printf("%d\n", test2->value);
}
这也有效。但是,有什么区别呢?为什么char*
使用?
注意:我以前void*
只是看看这是否有效。由于char*
与问题无关struct
,我只是想,“如果我void*
在那里使用呢?”。一个更具体的问题可能是,为什么不使用int*
或float*
为什么char*
使用?
解决方案
为什么使用指向字符的指针
为什么 desc 转换为 char*?......因为
char*
与问题无关struct
......</p>
在 C 中,除了位域之外的每个对象都由字节序列组成。1将对象的地址转换为指向对象char *
第一个字节的指针,您可以使用该指针访问对象的各个字节。
在标准 C 中,指针算术使用指向类型的单元。p
对于类型的指针struct Test
,p+1
指向 之后的下一个结构p
,p+2
指向之后的结构,依此类推。q
对于类型为 的指针char *
,q+1
指向 q 之后的下一个,指向char
q之后,依此类推。q+2
char
因此,要访问对象的各个字节,您可以将其地址转换为 achar *
并使用它。
为什么不使用其他类型的指针
一个更具体的问题可能是,为什么不使用
int*
或float*
为什么char*
使用?
char *
之所以使用,是因为 C 中的所有对象(位域除外)都被定义为表示为字节序列。它们不一定是int
or的序列float
。unsigned char *
并且signed char *
也可以使用,并且unsigned char *
由于符号问题的并发症可能更可取。
C 标准有关于使用字符指针访问对象的特殊规则,因此它保证以这种方式访问对象的字节是可行的。相反,使用int *
or访问对象float *
可能不起作用。允许编译器期望指向 an 的指针int
不会用于访问float
对象,并且当它为程序生成机器指令时,它可能会根据该期望编写这些指令。使用字符指针可防止编译器假定 achar *
与另一种指针指向的位置不同。
为什么指向无效工作的指针
注意:我以前
void*
只是看看这是否有效。
为了使指针算法起作用,编译器需要知道指向对象的大小。将 1 添加到指向 a 的指针时struct Test
,编译器需要知道调整内部地址的字节数。
void
是不完全类型。没有void
物体,void
也没有大小。(大小不为零。没有大小。)因此,C 标准没有定义p+1
when p
is a 的任何含义void *
。
但是,GCC 将算术 on 定义void *
为扩展。它就像void
大小为 1 字节一样工作。Clang 也支持这一点。
由于这个扩展,用指针做算术void *
本质上和用指针做算术是一样的char *
。
这个扩展是不必要的;任何进行算术运算的代码void *
都可以重写以char *
替代使用。有时这需要额外的强制转换来转换指针类型,这可能就是将扩展添加到 GCC 的原因(以减少所需的代码量并使其看起来更好)。
您可以使用开关禁用此扩展-Werror -Wpointer-arith
,或者您通常可以使用-Werror -std=c18 -pedantic
. 我-Werror -std=c18 -pedantic
尽可能使用它,我推荐它。
脚注
1位域是保存在一些较大的字节容器中的位序列,可能恰好与字节重合。
推荐阅读
- excel - 显示之前在用户表单上输入的数据并允许编辑数据
- python - 布尔值和整数之间的身份比较
- javascript - 为什么有时 XMLHttpRequest 会被 CORS 阻止,而我的本地 IP 地址位于 access-control-allow-origin 中?
- ios - 在没有电子邮件 ID 的情况下使用 Apple 登录
- python - 在while循环Python中将数字添加到字符串的问题
- flutter - 导入某些 Flutter 包时出现问题
- python - “无法导入 Python 映像库”
- arrays - 如何使用 *ngfor 读取和显示数组数组?
- ios - 来自 ARKit 的 DeviceMotion 数据
- python - 尝试 pip install cantools 时退出状态 1