提问人:Sasha 提问时间:10/3/2023 更新时间:10/3/2023 访问量:58
将不同类型的指针传递给函数 (C)
passing a pointer of different type to a function (C)
问:
假设一个来自通用库的函数在任何情况下都想使用长整数(比如 64 位),但在我的程序中我想使用短整数(比如 32 位)。然后我遇到如下情况:
void f(long unsigned int *a) {
*a = 10;
}
void main(void) {
unsigned int b;
f(&b);
return;
}
我是否正确理解这实际上不是一个好主意,并且函数 f 将覆盖另外 32 位(内存中的位),写入其中(当编译器从 到 时)?但是,如果我想象正确,以下内容不会覆盖(因为编译器从 转换为):b
0
unsigned int *
long unsigned int *
long unsigned int
unsigned int
long unsigned int f(void) {
return 10;
}
void main(void) {
unsigned int b;
b = f();
return;
}
这是对的吗?
第二个实现有一个缺点,以防函数返回计算的其他部分对我来说很方便,而这只是计算的额外细节......10
答:
我是否正确理解,这实际上不是一个好主意
是的,这是正确的。
...并且函数 f 将覆盖另外 32 位(内存中 b 后面的位),将 0 写入其中(当编译器从 到 时)?
unsigned int *
long unsigned int *
这是一种可能性。也可能有比 AN 更严格的对齐要求,因此它甚至可能在走到那一步之前就崩溃了。unsigned long int*
unsigned int*
如果你有这样的接口,你通常会做的是提供正确类型的变量,然后将其分配给所需类型的变量:
void f(unsigned long int *a) {
*a = 10;
}
void main(void) {
unsigned long int tmp;
f(&tmp);
// if (tmp > UINT_MAX) ... // possible error check
unsigned int b = tmp;
}
评论
关键问题是用于访问对象的类型。在 中,参数声明为 。这意味着,在 里面,指的是 .特别是,表示“将值 10 写入 .f
a
long unsigned int *a
f
*a
long unsigned int
*a = 10;
long unsigned int
在 中,定义为 。然后将 an 的地址传递给 。main
b
unsigned int b
f(&b)
unsigned int
f
所以说将 a 的字节写入实际上是 .*a = 10
long unsigned int
unsigned int
如果 是 64 位且是 32 位,则表示名义上尝试写入的位数多于对象的位数。它可能会写入对象外部的内存,这可能会损坏程序用于其他目的的数据。它还可能尝试访问进程有效地址空间之外的内存,这将导致陷阱,从而结束程序的执行。long unsigned int
unsigned int
f
但是,无论内存访问的细节如何,此代码的行为都不是由 C 标准定义的。C 2018 6.5 7 指定了有关应使用哪种类型访问对象的规则。对于 ,这些规则允许使用以下类型访问它:unsigned int
unsigned int
,unsigned int
使用限定符(例如 or ),const
volatile
int
(signed int
),带或不带限定符,- 以上述项之一为成员的数组、结构或联合类型,或
- 字符类型。
由于以上都不是,因此不符合规则。即使宽度相同,它也是不兼容的不同类型的,所以它不符合规则。long unsigned int
long unsigned int
unsigned int
unsigned int
即使它是相同的宽度,因此名义上不会访问比实际拥有的更多的内存,违反 6.5 7 中的规则意味着编译器可能会在优化时对程序做出“不正确”的推断,然后优化可以以您意想不到的方式转换您的程序。*a = 10
b
评论
b
0
评论
long unsigned int
始终至少与 一样大。因此,由于有可能对某些东西造成损坏,因此不要这样做。在评论中的附属问题中,它可能但不寻常地与它的大小相同(始终至少至少为 16 位),因此在这种情况下,它会更加危险。如果函数指针的类型小于传递的类型,则不会设置其所有字节。unsigned int
unsigned char
unsigned int
void f(long unsigned int *a)
需要指向 的指针。其他任何事情都可能“有效”,但都是未定义的行为。long unsigned int