【问题标题】:when assigning to void pointer in C在 C 中分配给 void 指针时
【发布时间】:2013-01-08 10:03:38
【问题描述】:

我认为在将值分配给指针时,您应该使用 * 运算符,但我看到了类似的代码

char *a;
void *b;
b = "Hello";
a = b;
printf("%s", a);

当我编译它并打印 Hello 时这是合法的。不需要指向无效解除引用的指针吗?

【问题讨论】:

  • 你想错了。 * 用于分配给pointee
  • 是的,我的术语不正确,但是您从上面的代码中知道我的意思吧?
  • 您的代码中不涉及解引用。只有地址分配给指针。为了使这个分配工作 l.h.s 和 r.h.s 必须兼容,即:具有相同的数据类型。 void 指针是一个特殊的指针,它可以指向任何 type,您可以将 void 指针类型转换回它所指向的确切类型。在 C 中,您可以在没有任何显式转换的情况下执行此操作,因为它是一种弱类型语言,而在 C++ 中则需要显式转换。
  • @Jong-BeomKim:我不认为这只是你的“术语”。感觉更像是一种真正的误解,而您在语言中混淆源和目标的事实只是一个症状。一旦你以正确的方式思考这个问题,我相信这个问题的答案对你来说是显而易见的。
  • @Kerrek SB:不,我知道 * 用于为指针指向的内容分配值。我的问题只是关于 void 的指针。我的 C 教程仅显示了上面的代码示例,并没有解释为什么在使用指向 void 的指针时不需要 * 运算符。无论如何,谢谢你的回答。我应该使用准确的术语。

标签: c pointers void assign


【解决方案1】:

这“有效”是因为 void *char * 能够保存任何类型的指针。例如,如果您使用int *a; 而不是void *a;,您可能会遇到麻烦。

但是,您的代码没有取消引用 void 指针,并且 printf 函数在将参数从列表中的变量参数中拉出时将其转换为 char *。因此,您的代码中没有取消引用 void 指针。如果您的指针在某些类型的机器上没有完美地转换为char *(例如,如果我们有一个int *a;),这些机器在没有“额外信息”的情况下无法寻址字节(有些机器只有“指针”指向整个机器字,并且额外的信息用于在读取字节时存储您想要的那个字中的哪个字节),那么您的 printf 很可能无法正确操作 [“未定义的行为”]。

【讨论】:

  • 他为什么会惹上麻烦,我无法理解。
  • 因为在某些机器上,所有指针的大小都不相同。一些指针(通常是void *char *)需要“机器字内的字节”额外信息。对于指向整个机器字的指针,这不是必需的 - 所以如果int 是一个机器字,那么它将没有该信息,当然,如果信息不存在,一些奇怪的事情当函数(例如printf)读回指针并认为信息确实存在时会发生。
【解决方案2】:

C 中没有字符串类型。您可以将指向char 数组开头的char* 视为字符串。这正是printf 对待a 的方式。

据我所知,C 标准要求 char*void* 可以互换。

【讨论】:

  • char *void * 的互换性在这里实际上并不相关,因为转换是 X * -> void * -> X *,这保证是单射的对于所有非函数类型X,而不仅仅是char
  • 谢谢,我认为您的回答是最接近我的问题的答案。我google了一段时间,发现字符串文字本身只是一个地址,所以代码中的变量'b'是一个指针,也是字符串文字。
  • @Dietrich Epp:我想他只是指出旧的 K&R C 中没有 void* 而是使用了 char*。
【解决方案3】:

指向 void 的指针不需要解引用,事实上,解引用 void 指针是非法的。您显然可以将任何指针转换为 void 指针,并将 void 指针转换为任何其他指针类型。

这就是为什么:

void *b = "hello world"; 有效,char *a = b 也有效,然后将 a 打印出来。 这里发生的是:

char *a; // declares a as a pointer to char
void *b; // declares b as a void pointer(which can hold an address)
b = "Hello"; // 'b' now holds the address, that points to the start of "Hello"
a = b; // now, 'a' contains the address that 'b' does
printf("%s", a); // prints the string, starting from the address pointed by 'a'.

因此这是完全合法的。

【讨论】:

  • 不会 int* b= "hello world" 也可以吗?
【解决方案4】:

b = "Hello"; 这一行分配了一堆char内存,并将其地址分配给void指针变量b

void 指针可以存储任何其他数据类型的地址。 void 指针的唯一限制是:

  • 由于显而易见的原因,无法取消引用 void 指针
  • sizeof(void) 是非法的
  • 您不能对 void 指针执行指针运算

但是 GCC 假定 sizeof(void) 为 1 并允许对 void 指针进行指针运算。

a=b; 这是典型的 char 指针 a 初始化为包含在 void 指针 b 中的地址。这是合法的,但如果滥用可能会产生影响。

printf("%s", a); 这是一个简单的 printf 语句。

这段代码中的一切都很好。

是的,您需要使用* 为指针中分配的内存分配一个值: 例如:

   char *c=malloc(sizeof(char));
   *c='a';

   char a='a';
   char *c=&a;
   *c='b';

在使用双指针时,您还将使用* 来初始化另一个指针。

   char *a=NULL;
   mymalloc(&a);


   void mymalloc(char **a)
   {
     *a=malloc(10);
     return;
   }

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2014-05-13
    • 1970-01-01
    • 2015-01-15
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 2022-07-06
    相关资源
    最近更新 更多