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

标签 c void-pointers

谁能解释为什么我没有得到变量的值,而是得到它的内存?

我需要使用 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*)。该类型转换不是可移植的东西/好主意。使用 %pprintf 一个指针。

同样,您在这里进行了“错误转换”: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/

相关文章:

c - 使用 void 指针在 C 中重新编程 Calloc/Realloc

c - C中的二进制文件读/写

c - 段错误释放内存 - 仅当分配的内存太多时

c++ - Protobuf 声明我缺少必填字段,而我显然不是

c++ - C->C++ 在未给出类型的情况下,在#define 中自动将 void 指针转换为 C++ 中的类型指针(C 风格)[MSVS]

c - 将函数作为 void * 传递,其参数也作为 void *

c - 类型为 void 的数组

c - void 表达式的无效使用

c - 段错误读取具有区域设置的宽向流

c - 以太网头的长度一定是 14 吗?