谁能解释为什么我没有得到变量的值,而是得到它的内存?
我需要使用 void* 来指向“unsigned short”值。
据我了解,void 指针的大小和类型都是未知的。
然而,一旦初始化它们,它们就为人所知,对吧?
为什么我的 printf 语句打印出错误的值?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int a, void *res){
res = &a;
printf("res = %d\n", *(int*)res);
int b;
b = * (int *) res;
printf("b =%d\n", b);
}
int main (int argc, char* argv[])
{
//trial 1
int a = 30;
void *res = (int *)a;
func(a, res);
printf("result = %d\n", (int)res);
//trial 2
unsigned short i = 90;
res = &i;
func(i, res);
printf("result = %d\n", (unsigned short)res);
return 0;
}
我得到的输出:
res = 30
b =30
result = 30
res = 90
b =90
result = 44974
最佳答案
要记住的一件事:C 不保证 int
足够大以容纳指针(包括 void*
)。该类型转换不是可移植的东西/好主意。使用 %p
来 printf
一个指针。
同样,您在这里进行了“错误转换”:void* res = (int*) a
告诉编译器:“我确信 a< 的值
是一个有效的 int*
,所以你应该这样对待它。”除非您确实知道内存地址 30 处存储了一个 int
,否则这是错误的。
幸运的是,您立即用 other a
的地址覆盖了 res
。 (您有两个名为 a
的变量和两个名为 res
的变量,一个在 main
中,另一个在 func
中。 func
中的值是 main
中值的副本,当你在那里调用它时。)一般来说,将参数的值覆盖到函数是“错误的形式”,但它在技术上是合法的。就个人而言,我建议在 99% 的情况下将所有函数的参数声明为 const
(例如 void func (const int a, const void* res)
)
然后,您将 res
转换为 unsigned short
。我认为没有人仍在 16 位地址空间 CPU 上运行(好吧,你的 Apple II,也许),所以这 肯定 会破坏 res
的值通过截断它。
一般来说,在 C 语言中,类型转换是危险的。您正在否决编译器的类型系统,并说:“看这里,编译器先生,我是程序员,我比你就是我这里的东西。所以,你只要保持安静,让这一切发生。”从指针转换为非指针类型几乎是普遍错误的。指针类型之间的转换往往是错误的。
我建议查看此页面下方的一些“相关”链接,以找到有关 C 类型和指针一般如何工作的良好概述。有时需要多读几遍才能真正掌握这些东西是如何组合在一起的。
关于c - 如何在 C 中正确使用 void 指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8448750/