为什么在将地址在指针中的内存中打印之前,我们必须将void指针强制转换为int或其他内容?

4 c pointers void void-pointers dereference

我不知道为什么是有必要铸造的void指针,int *char *打印地址的内容存储器之前,即使我们告诉printf()函数如何解释在内存中的数据?

假设我们有以下代码:

int main (void)
{
 void* c = malloc(4);
 printf("%d",*c);
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么不可能这样做?

所以要明确我的问题是这是不可能的原因是什么?

编辑: 在所有的答案和研究之后,我仍然不确定编辑中的致命错误究竟在哪里.我感到困惑的主要原因是我的编译器(gcc)在告诉"取消引用void指针"时只给出一个警告.这是实际的错误吗?据我所知,即使有警告,该程序仍应编译.

EDIT2 我仍然感到困惑的是我们有一个ERROR和WARNING的原因看起来是完全独立的,但是由同一段代码生成:

pointer.c:7:13: warning: dereferencing 'void *' pointer                                                                                                                                                           
 printf("%d",*p);                                                                                                                                                                                                 
             ^~                                                                                                                                                                                                   
pointer.c:7:13: error: invalid use of void expression                                                                                                                                                             
 printf("%d",*p);
Run Code Online (Sandbox Code Playgroud)

有些用户说只有在我们尝试使用derefenciation的结果时才会出现错误,并且警告是在我们为VOID指针实际分配内存时.

显然不是这种情况,因为如果我们删除printf行,我们确实只会得到一个警告但是完全没有一个警告.

pointer.c:6:8: warning: unused variable 'p' [-Wunused-variable]                                                                                                                                                   
 void * p=malloc(4);    
Run Code Online (Sandbox Code Playgroud)

Sou*_*osh 8

问题不在于解释printf(),而在于解除引用.

在类似声明的情况下

 printf("%d",*c);
Run Code Online (Sandbox Code Playgroud)

你试图取消引用a void *.现在,这void是一个永远不完整的类型.你不能取消引用一个指向"不完整的东西"的指针,并因此得到一些有意义的东西.

引用C11,章节§6.2.5,P19

void类型包含一组空值; 它是一个不完整的对象类型,无法完成.

换句话说(虽然我自己有点),C是一种强类型语言,对于每种定义的类型,编译器知道(或必须知道)它需要读取 /操作的内存中有多少字节(大小)上.对于一个void类型,编译器是无能为力的.

出于同样的原因,void *s 上也不允许使用指针算法.GCC有它的延伸对待一个void*相同的char *,但是这是一个扩展,而不是标准.


编辑:

我的编译器为语句生成错误,在线检查.


gsa*_*ras 5

*c取消引用指针,它是类型void(不完整类型).您不能取消引用void,因为编译器不知道类型(因此它的大小).因此,取消引用void指针会调用Undefined Behavior.

换句话说,取消引用void指针是不合理的.想象一下你是编译器,你如何插入指针所指向的内存(因为它可以是任何东西)?将a void*转换为正确的类型将起到作用(向编译器提供nessecairy信息).

为什么编译器只发出警告而不是错误?

确实如此,请注意它会生成警告和伴随错误:

main.c:8:14: warning: dereferencing 'void *' pointer
  printf("%d",*c);
              ^~
main.c:8:14: error: invalid use of void expression
printf("%d",*c);
^~~~~~
Run Code Online (Sandbox Code Playgroud)

(gcc)在讲述"取消引用void指针"时给出了一个警告.这是实际的错误吗?

没有.

但是试图使用这种去除反应的结果,你运气不好.

我的意思是:

void* c = malloc(4);
*c;
Run Code Online (Sandbox Code Playgroud)

不会导致错误(但只是一个警告):

main.c:6:2: warning: dereferencing 'void *' pointer
  *c;
  ^~
Run Code Online (Sandbox Code Playgroud)

但是,如果您尝试使用结果*c,则会生成错误.

阅读更多关于理解无效指针的内容.