我试图理解C和C++之间关于void指针的区别.以下编译用C而不是C++编译(所有编译都用gcc/g ++ -ansi -pedantic -Wall完成):
int* p = malloc(sizeof(int));
Run Code Online (Sandbox Code Playgroud)
因为malloc返回void*,C++不允许分配,int*而C允许.
但是,这里:
void foo(void* vptr)
{
}
int main()
{
int* p = (int*) malloc(sizeof(int));
foo(p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
C++和C都编译它没有抱怨.为什么?
K&R2说:
任何指向对象的指针都可以转换为类型
void *而不会丢失信息.如果结果转换回原始指针类型,则恢复原始指针.
这很好地总结void*了C中的转换.C++标准规定了什么?
我在旧的C代码中看到了很多以下内容:
type_t *x = (type_t *) malloc(...);
Run Code Online (Sandbox Code Playgroud)
从那里malloc()开始返回指针的重点是什么void *?是因为较旧的C编译器不支持void指针而是malloc()习惯返回char *?
来自Linux的man shmat逐字:
返回值
返回错误(void*)-1,并设置errno以指示错误原因.
(POSIX使用略有不同的措辞来讲述相同的内容.)
是否有任何强制性规则或定义(标准?)(void *) -1可能不是有效地址?
鉴于我需要在结构中存储"泛型"指针的值并且对指向的内存本身没有兴趣,我发现将它存储为intptr_t比a 更为语义正确void*.问题是a uintptr_t是否更适合,并且当一个人更喜欢另一个人时?
问题:隐式bool转换是否总是回退到尝试隐式转换为void*?(如果存在类型的转换函数).如果是这样,为什么?
考虑以下简短程序:
#include <iostream>
class Foo{
public:
operator void*() const
{
std::cout << "operator void*() const" << std::endl;
return 0;
}
};
int main()
{
Foo f;
if(f)
std::cout << "True" << std::endl;
else
std::cout << "False" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出是:
operator void*() const
False
Run Code Online (Sandbox Code Playgroud)
意思是,void*被称为转换函数.如果我们explicit在转换函数前面标记限定符,则隐式转换void*将失败.
编辑:
似乎很多答案是"空指针可以转换为false".我理解这一点,我的问题是关于"如果我不能直接调用operator bool()那么我将尝试转换为任何指针".
我%p在Stack Overflow中已经阅读了很多关于C语言中格式说明符用法的答案,但似乎没有一个解释为什么void*所有类型都需要显式转换为char*.
我当然知道这样一个事实,即强制转换的要求void*与使用可变函数(参见本答案的第一条评论)有关,而非强制性要求.
这是一个例子:
int i;
printf ("%p", &i);
Run Code Online (Sandbox Code Playgroud)
产生关于类型不兼容性的警告,并且&i应该进行铸造void*(根据标准的要求,再次参见此处).
虽然这一大块代码能够顺利编译,但没有关于类型转换的任何投诉:
char * m = "Hello";
printf ("%p", m);
Run Code Online (Sandbox Code Playgroud)
如何char*从这一要求中"解脱"?
PS:可能值得补充的是我在 x86_64架构上工作,因为指针类型大小依赖于它,并且使用 gcc作为linux上的-W -Wall -std=c11 -pedantic编译器和编译选项.
来自OO(C#,Java,Scala),我非常重视代码重用和类型安全的原则.上述语言中的类型参数可以完成这项工作并启用通用数据结构,这些结构既是类型安全的,也不会"浪费"代码.
当我陷入C时,我意识到我必须做出妥协,我希望它是正确的.我的数据结构void *在每个节点/元素中都有一个,我失去了类型安全性,或者我必须为我想要使用它们的每种类型重新编写我的结构和代码.
代码的复杂性是一个显而易见的因素:遍历数组或链接列表是微不足道的,并且添加*next一个结构不是额外的努力; 在这些情况下,不尝试重用结构和代码是有道理的.但对于更复杂的结构,答案并不那么明显.
还有模块化和可测试性:将类型及其操作与使用该结构的代码分离,使测试更容易.反之亦然:在一个结构上测试某些代码的迭代,同时它试图做其他事情变得混乱.
那么你的建议是什么?void *和重用或类型安全和重复的代码?有没有一般原则?当我不适合时,我是否试图强迫OO进行程序化?
编辑:请不要推荐C++,我的问题是关于C!
我有一个incr函数来增加值1
我希望使它成为通用的,因为我不想为相同的功能创建不同的函数.
假设我要增加int,float,char由1
void incr(void *vp)
{
(*vp)++;
}
Run Code Online (Sandbox Code Playgroud)
但我知道的问题是Dereferencing a void pointer is undefined behaviour.有时可能会出错:Invalid use of void expression.
我的功能main是:
int main()
{
int i=5;
float f=5.6f;
char c='a';
incr(&i);
incr(&f);
incr(&c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
问题是如何解决这个问题?是否有解决这个问题的方式C只有
要么
我是否必须incr()为每种数据类型定义?如果是,那么有什么用呢void *
同样的问题swap()和sort().我想交换和整理各种数据类型的功能相同的.
在学习了一些教程并阅读有关函数指针的内容后,我了解到显然在ISO C中为函数指针指定了一个void指针是未定义的,有没有办法解决我在编译期间收到的警告(例如更好的编码方式)或我应该忽略它吗?
警告:
ISO C forbids assignment between function pointer and 'void *' [-pedantic]
Run Code Online (Sandbox Code Playgroud)
示例代码:
void *(*funcPtr)();
funcPtr = GetPointer();
Run Code Online (Sandbox Code Playgroud)
GetPointer是一个返回void指针EG的函数
void *GetPointer();
Run Code Online (Sandbox Code Playgroud) 我有一个功能:
int foo(void * ptr)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
我可以在C++ 11/14中语法上(不使用编译器警告等)禁用传递除void *自身以外的指针吗?
例如,现在它可以被称为:
foo(new int(42));
Run Code Online (Sandbox Code Playgroud)
我需要禁用它.