我继承了一个最初用C编写的大应用程序(但同时也添加了很多C++).由于历史原因,该应用程序包含许多void指针.在你开始窒息之前,让我解释为什么这样做.
该应用程序包含许多不同的数据结构,但它们存储在"通用"容器中.现在我会使用模板化STL容器,或者我会给所有数据结构一个公共基类,这样容器可以存储指向基类的指针,但是在[好?]旧C天,唯一的解决方案是将struct-pointer强制转换为void-pointer.
另外,有很多代码可以在这些void指针上运行,并使用非常奇怪的C结构来模拟C中的多态性.
我正在重新编写应用程序,并试图摆脱虚空指针.为所有数据结构添加一个公共基类并不困难(几天的工作),但问题是代码充满了如下所示的结构.
这是数据存储方式的示例:
void storeData (int datatype, void *data); // function prototype
...
Customer *myCustomer = ...;
storeData (TYPE_CUSTOMER, myCustomer);
Run Code Online (Sandbox Code Playgroud)
这是再次获取数据的示例:
Customer *myCustomer = (Customer *) fetchData (TYPE_CUSTOMER, key);
Run Code Online (Sandbox Code Playgroud)
我实际上想用一些智能指针(引用计数)替换所有的void指针,但我找不到一个自动化(或至少)帮助我摆脱所有转换的技巧 - 指针.
有关如何以这些转换的任何可能方式查找,替换或互动的任何提示?
在C中,指向和来自指针并不是错误void *.
移植到C++的一个主要障碍是需要在从处理泛型指针的函数返回时转换指针,例如malloc,在我自己的代码中声明的函数void *block_get(Blkno const blkno);.
然而,我的代码应该由C 和 C++编译器成功编译.如果我为了C++而在任何地方提供显式的强制转换,它们必须是C风格的强制转换,并且我可能会因为从两种语言的指针类型转换非指针类型而屏蔽错误.
我的参考错误如下:
struct Cpfs *cpfs = calloc(1, sizeof(*cpfs));
Run Code Online (Sandbox Code Playgroud)
在MSVC中产生:
错误2错误C2440:'初始化':无法从'void*'转换为'Cpfs*'e:\ src\cpfs\cpfs.c 179
显然,如果我不再使用C,我就不能使用new或者static_cast我自然会使用.对于每种语言提供最大类型安全性的最佳方法是void *什么?最简单的问题是什么?
为什么我不能通过void*参考传递?编译器允许我使用以下签名声明一个函数:
static inline void FreeAndNull(void*& item)
Run Code Online (Sandbox Code Playgroud)
但是当我尝试调用它时,我收到以下错误:
Error 1 error C2664: 'FreeAndNull' : cannot convert parameter 1 from 'uint8_t *' to 'void *&'
Run Code Online (Sandbox Code Playgroud)
将它投射到void*也不起作用
另外,有任何变通方法吗?
假设在我的代码中,我必须存储一个void*as数据成员,并class在需要时将其强制转换回原始指针.为了测试它的可靠性,我写了一个测试程序(linux ubuntu 4.4.1 g ++ -04-Wall),我很震惊地看到了这个行为.
struct A
{
int i;
static int c;
A () : i(c++) { cout<<"A() : i("<<i<<")\n"; }
};
int A::c;
int main ()
{
void *p = new A[3]; // good behavior for A* p = new A[3];
cout<<"p->i = "<<((A*)p)->i<<endl;
((A*&)p)++;
cout<<"p->i = "<<((A*)p)->i<<endl;
((A*&)p)++;
cout<<"p->i = "<<((A*)p)->i<<endl;
}
Run Code Online (Sandbox Code Playgroud)
这只是一个测试程序; 实际上,对于我的情况,必须将任何指针存储为void*,然后将其转换回实际指针(借助于template).所以我们不要担心这一部分.上面代码的输出是,
p->i = 0
p->i = 0 // ?? …Run Code Online (Sandbox Code Playgroud) c++ reference strict-aliasing void-pointers reinterpret-cast
我正在编写一个解释器,我希望能够将函数返回的任何值存储到void指针中.我没有问题存储int和各种指针作为void指针,但我在尝试将double作为void指针进行转换时遇到错误.我知道双精度存储的位置与整数和指针位不同,但我不明白为什么我不能将任何我想要的位放入指针(假设它有足够的内存分配),然后将它们取出,把它们当成双重的.
是否可以使用我不知道的语法将双精度转换为void指针,或者我是否误解了void指针的工作原理?
因为这是一个空*我应该能够传递任何类型的指针吗?为什么编译器会给我错误?
int cmp_func(void *, void *));
typedef struct word_{
char key[WORD_SIZE];
int *frequency;
} word;
Phash_table new_hash(int size, int (*hash_func)(char *), int (*cmp_func)(void *\
, void *));
int comp_function(struct word_ *word1,struct word_ *word2){
if( word1->frequency < word2->frequency){
return -1;
}
if(word1->frequency < word2->frequency){
return 1;
}
if(word1->frequency == word2->frequency){
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
project4_functions.c:47:3: warning: passing argument 3 of 'new_hash' from incompatible pointer type [enabled by default]
hash.h:38:13: note: expected 'int (*)(void *, void *)' but argument is of type …Run Code Online (Sandbox Code Playgroud) 我有以下代码段:
char* filename;
unsigned long long int bytesToTransfer;
int fd, pagesize;
char *data;
fd = open(filename, O_RDONLY);
if (fd==NULL){
fputs ("File error",stderr);
exit (1);
}
cout << "File Open: " << filename << endl;
pagesize = getpagesize();
data = mmap((caddr_t)0, bytesToTransfer, PROT_READ, MAP_SHARED, fd, 0);
if (*data == -1) {
fputs ("Memory error",stderr);
exit (2);
}
cout << "Data to Send: " << data << endl;
Run Code Online (Sandbox Code Playgroud)
但是当我编译时,我会收到:
错误:从'void*'到'char*'的无效转换[-fpermissive] data = mmap((caddr_t)0,bytesToTransfer,PROT_READ,MAP_SHARED,fd,0);
有人能给我一个暗示什么是错的吗?
我需要在源代码中找到所有这些地方,其中隐式转换任何类型的指针void *或停止这些隐式转换的方法.
例如:
int * 至 void *char * 至 void *Base * 至 void *是否有任何gcc警告或错误标志,它会检测指针被隐式转换为的所有这些行void *?
考虑以下代码:
void **v_dptr(nullptr);
int **i_dptr = static_cast<int**>(v_dptr);
Run Code Online (Sandbox Code Playgroud)
上面的示例产生以下编译错误:
static_cast from 'void **' to 'int **' is not allowed
我知道将void指针强制转换为任何其他指针类型的正确方法是使用static_cast.但是,您不能static_cast将void指针指向其他类型的另一个双指针.
static_cast双void指针?void指针的正确方法?我很困惑为什么我的编译器在以下情况下抛出错误:
void funcExample (void * p_Buf, uint16_t len)
{
uint16_t i;
for (i = 0; i < len; i++) {
otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue
}
}
Run Code Online (Sandbox Code Playgroud)
但是如果我在传递给otherFunc之前进行转换,那很好,因为增加非void指针没有问题:
void funcExample (void * p_Buf, uint16_t len)
{
uint16_t i;
uint8_t * p_Buf_8bit;
p_Buf_8bit = (uint8_t *) p_Buf;
for (i = 0; i < len; i++) {
otherFunc (p_Buf_8bit++);
}
}
Run Code Online (Sandbox Code Playgroud)
一旦施放,无法将void指针递增?我错过了一些基本的东西吗?
void-pointers ×10
c++ ×7
c ×6
pointers ×4
casting ×2
reference ×2
function ×1
mmap ×1
parameters ×1
structure ×1