我想知道为什么id是弱引用指针,它如何处理任何class类型指针,在运行时我们如何检测分配给哪种类型的类指针id.
在C++中,您可以使用模板同时拥有通用容器和类型安全容器.但是在C中,如果你想要通用容器,你必须(afaik)使用void*,这意味着你失去了类型安全性.要拥有类型安全的容器,您必须为要保留的每种类型的数据重新实现它们.
鉴于C遵循比C++ 更多的程序员知道他所做的理念,在C中做什么更惯用的事情:使用通用容器void*,或为每种类型的数据制作自定义容器?
好吧,我最初严重搞砸了我对这个问题的描述(自从我认真编写C++代码以来我已经超过一年了,我对纯C的经验非常有限),让我们再试一次.
编写一些C代码以期望您执行以下操作
void* p;
create_new_thing(&p); //p is now a new thing
do_stuff_to_thing(p); //something happened to p
Run Code Online (Sandbox Code Playgroud)
我的问题是如何p在Julia中创建对象.现在我相信答案
p = Ref{Ptr{Void}}()
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p)
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p)
Run Code Online (Sandbox Code Playgroud)
此外,我相信相同的代码,但p声明相反p = Array(Ptr{Void}, 1)也有效.
然而,我发现整个之间的区别Ref,并Ptr在朱莉娅非常混乱,主要是因为他们似乎的方式,我不能跟踪相互之间进行转换得到.
我有这个工作代码:
#import <stdlib.h>
#import <stdio.h>
typedef struct myarray {
int len;
void* items[];
} MYARRAY;
MYARRAY *collection;
void
mypop(void** val) {
puts(collection->items[collection->len]);
*val = collection->items[collection->len--];
}
void
mypush(void* val) {
int len = collection->len++;
collection->items[len] = val;
puts(collection->items[len]);
}
int
main() {
puts("Start");
collection = malloc( sizeof *collection + (sizeof collection->items[0] * 1000) );
collection->len = 0;
puts("Defined collection");
mypush("foo");
puts("Pushed foo");
mypush("bar");
puts("Pushed bar");
char str1;
mypop((void*)&str1);
puts("Popped bar");
puts(&str1);
char str2;
mypop((void*)&str2);
puts("Popped foo");
puts(&str2);
puts("Done");
return 0; …Run Code Online (Sandbox Code Playgroud) 以下代码可在VSC ++ 2017中编译且没有任何错误,并且不会在gcc 7.3.0(error: invalid static_cast from type ‘int(int)’ to type ‘void*’
void* p = static_cast<void*>(func))中编译
#include <iostream>
int func(int x) { return 2 * x; }
int main() {
void* p = static_cast<void*>(func);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我的程序需要使用void*来在动态调用情况下传输数据或对象,以便它可以引用任意类型的数据,甚至是原始类型.但是,我最近发现,在具有多个基类的类的情况下向下转换这些void*的过程失败,甚至在调用这些向下转换指针上的方法后崩溃我的程序,即使内存地址似乎是正确的.在访问"vtable"期间发生崩溃.
所以我创建了一个小测试用例,环境是Mac OS X上的gcc 4.2:
class Shape {
public:
virtual int w() = 0;
virtual int h() = 0;
};
class Square : public Shape {
public:
int l;
int w() {return l;}
int h() {return l;}
};
class Decorated {
public:
int padding;
int w() {return 2*padding;}
int h() {return 2*padding;}
};
class DecoratedSquare : public Square, public Decorated {
public:
int w() {return Square::w() + Decorated::w();}
int h() {return Square::h() + Decorated::h();}
};
#include <iostream>
template <class T> …Run Code Online (Sandbox Code Playgroud) 我想传递一个指向函数的"多态"数组.
我可以在没有警告的情况下做以下事情:
foo (void* ptr);
bar()
{
int* x;
...
foo(x);
}
Run Code Online (Sandbox Code Playgroud)
gcc显然会自动转换x为a (void*),这只是花花公子.
但是,当我执行以下操作时,我会收到警告:
foo (void** ptr);
bar()
{
int** x; // an array of pointers to int arrays
...
foo(x);
}
note: expected ‘void **’ but argument is of type ‘int **’
warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么一个传递(int*)的(void*)参数不是"不兼容",但(int**)作为一个(void**)论据是什么?
由于所有指针类型都是相同的大小(对吗?因为我使用了C已经有一段时间了),我仍然可以做类似的事情:
void mainFunc1(int** arr, int len)
{
//goal is to apply …Run Code Online (Sandbox Code Playgroud) 我正在用纯C编写通用链表实现.
struct Node {
void *value;
struct Node *next;
};
struct LinkedList {
struct Node *start;
struct Node *end;
};
void LinkedList_new(struct LinkedList* llist) {
llist->start = 0;
llist->end = 0;
return;
}
void addNode( struct LinkedList *ll, void *_value ) {
if ( NULL == ll->start ) {
ll->start = (struct Node *) malloc( sizeof(struct Node) );
ll->end = ll->start;
} else {
ll->end->next = (struct Node *) malloc( sizeof(struct Node) );
ll->end = ll->end->next;
}
ll->end->value = _value; …Run Code Online (Sandbox Code Playgroud) 在最后两行以下程序,static_cast<void*>并dynamic_cast<void *>表现不同.据我所知,的结果dynamic_cast<void*>总是解析为完整的对象的地址.所以它以某种方式使用RTTI.谁能解释一下编译器如何使用RTTI两者之间的区分.
#include <iostream>
using namespace std;
class Top {
protected:
int x;
public:
Top(int n) { x = n; }
virtual ~Top() {}
friend ostream& operator<<(ostream& os, const Top& t) {
return os << t.x;
}
};
class Left : virtual public Top {
protected:
int y;
public:
Left(int m, int n) : Top(m) { y = n; }
};
class Right : virtual public Top {
protected:
int z;
public:
Right(int m, …Run Code Online (Sandbox Code Playgroud) 我正在查看https://en.cppreference.com/w/cpp/language/reinterpret_cast,我注意到它指定了我们可以始终转换为的合法类型:
byte*char*unsigned char*但我并没有看到void*在列表中。这是疏忽吗?我的用例需要一个,reinterpret_cast因为我是从int**转换为void*。我最终会从void*后面投射到镜头上int**。
void-pointers ×10
c ×5
c++ ×4
pointers ×3
casting ×2
arrays ×1
containers ×1
dynamic-cast ×1
gcc ×1
generics ×1
idioms ×1
ios ×1
julia ×1
objective-c ×1
printf ×1
static-cast ×1
xcode ×1