嘿伙计们,我是C的新手,对于我的第一个项目,我需要实现一个基于数组的队列.我希望我的队列能够保存任何类型的对象,因此我创建了一个QueueElement结构来保存指向任何类型对象的void指针.我认为一切正常,除了我无法从QueueElement结构中读取'position'和'value'字段.我尝试编译时遇到以下错误.
错误:
Runnable.c: In function `main':
Runnable.c:10: error: dereferencing pointer to incomplete type
Runnable.c:11: error: dereferencing pointer to incomplete type
Run Code Online (Sandbox Code Playgroud)
我很确定我只是没有正确投射.任何帮助表示赞赏.
再次感谢,Pooch
Runnable.c
#include <stdio.h>
#include "Queue.h"
int main(void) {
int i = 9;
Queue q = CreateQueue();
QueueElement e = CreateQueueElement(&i);
Enqueue(q, e);
QueueElement f = Dequeue(q);
/* PROBLEM IS HERE */
printf("position: %d", f->position);
printf("value: %d", (int *)(f->value));
DestroyQueue(q);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include "QueueElement.h"
typedef struct QueueStruct *Queue;
Queue CreateQueue(void);
void DestroyQueue(Queue q); …Run Code Online (Sandbox Code Playgroud) 这与在此找到的问题标题完全相同- 我还想将一个内存地址存储在变量中 - 或者更确切地说,void*在变量中存储一个.但是,我宁愿将它存储在某种形式的int而不是a中string,因为我希望之后再将其转换回指针.
这是因为它是一个类的成员,我想用boost serialize序列化,如果我确实使用了一个void*,boost serialize可能会尝试存储指针所指向的内容,这在我看来不是很明智案件.
我需要32位和64位gcc和MSVC,所以基本上我想知道是否有一个内置的整数类型,它是同一平台上指针的大小.或者,我想我需要IFDEF自己的类型?
我将struct Person类型的数据传递给链表,因此每个节点的数据指针指向一个结构Person.
struct Person {
char name[16];
char text[24];
};
Run Code Online (Sandbox Code Playgroud)
我试图遍历列表并通过调用打印每个节点中的名称/文本
traverse(&list, &print);
Run Code Online (Sandbox Code Playgroud)
遍历的原型是:
void traverseList(struct List *list, void (*f)(void *));
Run Code Online (Sandbox Code Playgroud)
列表定义为:
struct List {
struct Node *head;
};
Run Code Online (Sandbox Code Playgroud)
我的print函数接受void*数据:
print(void *data) { .... }
Run Code Online (Sandbox Code Playgroud)
我知道我必须将数据转换为struct Person,对吗?
struct Person *person = (struct Person *)data;
printf("%s", person->name);
Run Code Online (Sandbox Code Playgroud)
我知道这是不够的,因为我得到了"从不兼容的指针类型初始化"警告.在这种情况下,如何成功投出空白*?谢谢.
我正在使用 python ctypes 和 libc 与供应商提供的 DLL 文件进行交互。DLL 文件的目的是从相机获取图像。
图像采集似乎运行没有错误;我遇到的问题是访问数据。
图像采集函数将 ctypes.c_void_p 作为图像数据的参数。
简化如下:
"""
typedef struct AvailableData
{
void* initial_readout;
int64 readout_count;
} imageData;
"""
class AvailableData(ctypes.Structure):
_fields_ = [("initial_readout", ctypes.c_void_p),
("readout_count", ctypes.c_longlong)]
"""
Prototype
Acquire(
CamHandle camera,
int64 readout_count,
int readout_time_out,
AvailableData* available,
AcquisitionErrorsMask* errors );
"""
>>> imageData = AvailableData()
>>> Acquire.argtypes = CamHandle, ctypes.c_longlong, ctypes.c_int,
ctypes.POINTER(AvailableData), ctypes.POINTER(AcquisitionErrorsMask)
>>> Acquire.restype = ctypes.c_void_p
>>> status = Acquire(camera, readout_count, readout_time_out, imageData, errors)
Run Code Online (Sandbox Code Playgroud)
我不完全理解该函数在做什么,因为在我运行该函数后,它imageData.initial_readout似乎是一个类型“long”(甚至不是 ctypes.c_long:只是“long”)。然而,它也有一个与之相关的价值。我假设这是存储数据的起始地址。
>>> type(imageData.initial_readout)
<type …Run Code Online (Sandbox Code Playgroud) 当我从主可执行文件中调用std :: function时,通过将其地址转换为/从中,我在插件中遇到段错误void*.我可以在几个自包含的行中重现这个问题:
#include <iostream>
#include <functional>
int main()
{
using func_t = std::function<const std::string& ()>;
auto hn_getter = func_t{[]() {
return "Hello";
}};
auto ptr = reinterpret_cast<void*>(&hn_getter);
auto getter = reinterpret_cast<func_t*>(ptr);
std::cout << (*getter)() << std::endl; // Bang!
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
即使我正在使用原始类型,它仍然是segfaulting.谁能看到我哪里出错了?
我正在开发一个将从 C# 调用的 C++ 插件。我尝试移植的 API 带有数百个函数,其中大多数只是具有相同名称但具有不同数据类型(如 、int和float)的重载char。
我不想一遍又一遍地在 C++ 和 C# 端编写相同的代码但使用不同的数据类型,而是想使用一个带有通用指针的函数重载。我的目标是使用static_castfromvoid*到int,float然后char使用第一个成功的。
C++ 端的一个简单测试函数:
void calculate(void* input1, void* input2)
{
float *i1 = static_cast<float*>(input1);
if(i1==NULL)
std::cout<<"Bad"<<std::endl;
else
std::cout<<*i1<<std::endl;
}
int main()
{
int input1 = 5;
int input2 = 10;
calculate(&input1,&input2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这应该输出“BAD”,但它似乎显示“7.00649e-45”,我认为这是一种未定义的行为。失败static_cast了,我不知道如何检查它是否成功。检查它是否NULL在这种情况下没有帮助。
是否可以检查void*反对static_cast是否成功?如果是这样,怎么办?
笔记:
这不是这个问题的重复。我不想从 中找出对象的类型void*。我只是想检查转换是否static_cast …
我处于一种情况,我需要一个指向未知类型对象的指针作为另一个类的成员。但是有效对象类型的列表在编译时是已知的。
说我有:
// A class templated on T
template<class T> class obj;
// Now assume there are some objects of types obj<...> somewhere else
obj<int> obj1;
obj<double> obj2;
// Now, manager needs to create a pointer for these objects
// in a specific manner at construction-time
// Say, we have to choose a canonical object (and set the other as secondary)
// manager shouldn't be templated on T because It needs
// to have multiple members of type obj<...>
template<class …Run Code Online (Sandbox Code Playgroud) 在 C++ 中实现某些数据结构时,需要能够创建一个包含未初始化元素的数组。正因为如此,拥有
buffer = new T[capacity];
Run Code Online (Sandbox Code Playgroud)
不适合,因为new T[capacity]初始化数组元素,这并不总是可能的(如果 T 没有默认构造函数)或期望的(因为构造对象可能需要时间)。典型的解决方案是分配内存并使用placement new。
为此,如果我们知道元素的数量是已知的(或者至少我们有一个上限)并在堆栈上分配,那么,据我所知,可以使用对齐的字节或字符数组,然后使用std::launder访问成员。
alignas(T) std::byte buffer[capacity];
Run Code Online (Sandbox Code Playgroud)
但是,它只解决了栈分配的问题,并没有解决堆分配的问题。为此,我假设需要使用对齐新,并写这样的东西:
auto memory = ::operator new(sizeof(T) * capacity, std::align_val_t{alignof(T)});
Run Code Online (Sandbox Code Playgroud)
然后将其转换为std::byte*orunsigned char*或T*。
// not sure what the right type for reinterpret cast should be
buffer = reinterpret_cast(memory);
Run Code Online (Sandbox Code Playgroud)
但是,有几件事我不清楚。
reinterpret_cast<T*>(ptr)如果 ptr 指向可与 T 进行指针互转换的对象,则定义结果。(请参阅此答案或https://eel.is/c++draft/basic.types#basic.compound-3)了解更多详细信息。我假设,将其转换T*为无效,因为 T 不一定与 new 的结果是指针可互转换的。但是,它是否为char*或定义明确std::byte?new为有效的指针类型(假设它不是实现定义的)时,它是否被视为指向数组第一个元素的指针,或者只是指向单个对象的指针?虽然,据我所知,在实践中很少(如果有的话)很重要,但存在语义差异,pointer_type + integer …c++ memory-management void-pointers dynamic-memory-allocation reinterpret-cast
void-pointers ×10
c++ ×5
pointers ×5
c ×4
32bit-64bit ×1
c++11 ×1
casting ×1
ctypes ×1
fwrite ×1
libc ×1
python ×1
std-function ×1
struct ×1
unions ×1
void ×1