【问题标题】:Can pointers store values and what is the use of void pointers?指针可以存储值吗? void 指针有什么用?
【发布时间】:2014-08-14 17:21:53
【问题描述】:

我知道指针用于存储另一个内存位置的地址。代码如下:

    #include <stdio.h>
    main()
    {
      int a=10;
      void *ptr=10;
      printf("%u",ptr);
    }

我的输出是:10

我们可以像上面的程序那样在指针中存储值吗? void指针的主要用途是什么?

【问题讨论】:

  • 由于缺少泛型,void* 常用于 C 中的容器。
  • “通用”一词是指模板吗?
  • @Jashaszun 在这种情况下, void 指针可以处理任何数据类型的变量。我说的对吗?
  • @kalyan 它可以指向任何类型的对象。我不确定您所说的“过程”是什么意思。不,它不像模板。 C++ 中的模板与void * 指针无关,它们以完全不同(且更安全)的方式工作。将它们视为等价物是错误的。

标签: c pointers


【解决方案1】:

我们可以像上面的程序那样在指针中存储值吗?

应该分配给指针变量的唯一值是:

  • 其他对象的地址(如int *foo = &amp;x;);
  • 函数地址(int (*fptr)(const char *, ...) = printf;);
  • 明确定义的系统访问点的地址(例如嵌入式系统上的通信端口或中断寄存器);
  • NULL(代表明确定义的“无处”)。

您不应该像在示例中那样使用指针变量来存储用于算术计算或显示的任意值。

声明

void *ptr=10;

应该提出诊断;您不能在没有强制转换的情况下直接将整数值分配给指针变量。您可能希望提高正在使用的编译器的警告级别。

声明

printf("%u",ptr);

调用未定义的行为,因为参数的类型 (void *) 与转换说明符所期望的 (unsigned int) 不匹配。从某种意义上说,它“有效”了它显示了您期望的价值,但这是运气问题,而不是设计问题。它可以很容易地打印出一个垃圾值。

void指针的主要用途是什么?

它用作“通用”指针类型。指向不同类型的指针不能直接相互分配; IOW,你不能这样做

char *foo;
double *bar;

foo = bar; // bzzt

没有明确地将bar 转换为char *

foo = (char *) bar;

同样,如果你有一个函数接受一个类型的指针参数,你不能用不同类型的指针调用它:

void f(char *);
...
double x;
f(&x);       // bzzt

此规则的一个例外是void * 类型的对象;无需演员就可以分配它们:

int x;
void *foo = &x;

以及采用void * 类型参数的函数可以接受任何对象指针类型的参数:

void f(void *);
...
double x;
int y;

f(&x);
f(&y);

它们用于实现有限形式的“通用”编程(其中算法相同,但类型不同)。典型的例子是qsort 库函数,它可以对任何类型的数组进行排序。

【讨论】:

    【解决方案2】:
    void *ptr=10;
    

    这不是有效的 C,您需要使用 (void *) 10 之类的强制转换进行显式转换。

    printf("%u",ptr);
    

    这不是有效的 C,您需要使用 (unsigned int) ptr 之类的强制转换进行显式转换。

    关于void指针的使用,它们是通用对象指针,因此您可以将任何对象指针类型的指针值分配给void *

    【讨论】:

    • 我正在使用 Turbo c 编译器...我的代码运行良好,无需任何类型转换。
    • @kalyan 您必须启用所有编译器警告并修复它们。
    • @ouah:Turbo C的最新版本是24岁;这可能是不可能的;)
    • @kaylan 编译器编译您的代码这一事实并不意味着所有编译器都会接受您的代码
    • 在现代 C 中,void *ptr = 10; 完全没有意义。这是一个违反约束,意味着任何符合要求的编译器都必须发出诊断消息。如果该诊断是警告而不是致命错误,则标准根本没有说明结果程序的行为。没有抱怨它的编译器是不合格的;要么应用选项以使您的编译器(尝试)符合要求,要么获得更新的编译器。 (可能接受它的编译器会将其视为void *ptr = (void*)10;
    【解决方案3】:

    常量10的类型是int;您正在将 int 分配给 void *。这太疯狂了,而且是错误的,当你打印ptr 的值时,绝对不能保证你会得到10。你不应该这样做。你不知道指针值是如何表示的,你也不必知道。你不在乎。

    void 指针的使用相当简单:它只是一种处理泛型指针的方法。例如,您可以通过存储指向所存储对象的void 指针来实现“某物”的容器。请注意,您不能取消引用它 - 您需要在这样做之前将其转换回有效指针。

    另外,附带说明一下,您应该使用%p 来打印指针。

    【讨论】:

    • int-to-pointer(反之亦然)的转换实现是不是定义的,不是未定义的? (仅在指针不能表示为 int 的情况下未定义)
    • @indiv 是的,这是正确的。我没有反驳。
    【解决方案4】:

    指针用于存储变量的地址(内存位置)。因此,它们的大小通常是操作系统的字大小(如 64 位操作系统中的 64 位 = 8 字节)。

    通过定义像intcharvoid这样的指针类型,我们限制了特定数据类型的指针的使用。

    1. 通过将常量值分配给指针void *ptr=10;,您可能已经存储了值,但这不是正确使用的指针,并且可能会在以后导致分段错误。始终使用指针来存储变量的地址,例如void *ptr = &amp;a;

    2. void 指针不定义它所指向的数据类型。我们可以在不知道变量数据类型的情况下使用 void 指针来存储变量的地址。

    【讨论】:

      【解决方案5】:

      不,您不能直接将值存储到指针,除非您将其引用到某些东西。 像 x=y 这样的指针赋值使 y 指向与 x 相同的指针。 您可以咨询此以获得更多信息访问http://cslibrary.stanford.edu/106/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-01-15
        • 2014-05-30
        • 2016-03-20
        • 2012-12-08
        • 1970-01-01
        • 1970-01-01
        • 2011-01-14
        相关资源
        最近更新 更多