如何在C中正确使用void指针?

use*_*785 6 c void-pointers

有人可以解释为什么我没有得到变量的值,而是它的内存而不是?

我需要使用void*来指向"unsigned short"值.

正如我理解的无​​效指针,它们的大小是未知的,它们的类型是未知的.
然而,一旦初始化它们,它们是已知的,对吧?

为什么我的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;
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出:

res = 30
b =30
result = 30
res = 90
b =90
result = 44974
Run Code Online (Sandbox Code Playgroud)

BRP*_*ock 9

要记住一件事:C不保证int足够大以容纳指针(包括void*).演员阵容不是一个便携式的东西/好主意.使用%pprintf的指针.

同样地,你在这里做了一个"糟糕的演员":void* res = (int*) a告诉编译器:"我确信它的值a是有效的int*,所以你应该这样对待它." 除非你确实知道int存储在存储器地址30 的事实,否则这是错误的.

幸运的是,你立即res另一个 地址覆盖a.(你有两个vars命名a,两个命名res,in main和in in func.当你在那里调用它时,那些是in func的值的副本main.)一般来说,将参数的值覆盖到一个函数是"糟糕的形式",但它在技术上是合法的.就个人而言,我建议将所有函数的参数声明为const99%的时间(例如void func (const int a, const void* res))

然后,你投res了一个unsigned short.我不认为任何人仍然在16位地址空间CPU上运行(好吧,也许是你的Apple II),所以这肯定会res通过截断它来破坏它的价值.

通常,在C中,类型转换是危险的.你正在推翻编译器的类型系统,然后说:"看看这里,Compiler先生,我是程序员,我比你知道的更好.所以,你只要保持安静就能实现这一点." 从指针转换为非指针类型几乎普遍是错误的.指针类型之间的转换通常是错误的.

我建议查看本页下面的一些"相关"链接,以便总体上了解C类型指针的工作原理.有时需要阅读一些才能真正掌握这些东西如何结合在一起.


Man*_*uro 6

(unsigned short)res
Run Code Online (Sandbox Code Playgroud)

是一个指针上的强制转换,res是一个内存地址,通过将它转换为无符号的short,你得到的地址值是unsigned short而不是十六进制值,以确保你得到一个正确的值,你可以打印

*(unsigned short*)res
Run Code Online (Sandbox Code Playgroud)

第一个强制转换(unsigned short*)res使void*指向指针的指针unsigned short.然后,您可以通过使用取消引用它来提取内存地址res指向的值*


Mar*_*ett 0

printf("result = %d\n", (int)res); 将 res (指针)的值打印为数字。请记住,指针是内存中的地址,因此这将打印一些看起来随机的 32 位数字。

如果您想打印存储在该地址的值,那么您需要 (int)*res - 尽管 (int) 是不必要的。

编辑:如果你想打印指针的值(即地址),那么你应该使用%p它本质上是相同的,但更好地格式化它并理解 int 和 poitner 的大小在你的平台上是否不同