取消引用指向 void 数组的指针
我正在尝试更多地了解 C 及其神秘的隐藏功能,并且我尝试制作一个包含指向 void 的指针的示例结构,旨在用作数组。 编辑:重要提示:这是针对原始 C 代码的。
假设我有这个结构。
typedef struct mystruct {
unsigned char foo;
unsigned int max;
enum data_t type;
void* data;
} mystruct;
我希望数据能够容纳无符号字符、无符号短整型和无符号长整型的 max 个,data_t 枚举包含 这 3 种情况的值。
enum Grid_t {gi8, gi16, gi32}; //For 8, 16 and 32 bit uints.
然后我有一个函数来初始化和分配这个结构之一,并且应该返回一个指向新结构的指针。
mystruct* new(unsigned char foo, unsigned int bar, long value) {
mystruct* new;
new = malloc(sizeof(mystruct)); //Allocate space for the struct.
assert(new != NULL);
new->foo = foo;
new->max = bar;
int i;
switch(type){
case gi8: default:
new->data = (unsigned char *)calloc(new->max, sizeof(unsigned char));
assert(new->data != NULL);
for(i = 0; i < new->max; i++){
*((unsigned char*)new->data + i) = (unsigned char)value;
//Can I do anything with the format new->data[n]? I can't seem
//to use the [] shortcut to point to members in this case!
}
break;
}
return new;
}
编译器没有返回警告,但我不太确定这个方法。这是使用指针的合法方式吗?
有更好的方法©吗?
我错过了打电话给它。像 mystruct* P; P = 新(0,50,1024);
工会很有趣,但不是我想要的。因为无论如何我都必须单独处理每个具体案例,所以选角似乎和联合一样好。我特别希望拥有比 32 位数组大得多的 8 位数组,因此联合似乎没有帮助。为此,我将其设置为一个长整型数组:P
I am attempting to learn more about C and its arcane hidden powers, and I attempted to make a sample struct containing a pointer to a void, intended to use as array.
EDIT: Important note: This is for raw C code.
Let's say I have this struct.
typedef struct mystruct {
unsigned char foo;
unsigned int max;
enum data_t type;
void* data;
} mystruct;
I want data to hold max of either unsigned chars, unsigned short ints, and unsigned long ints, the data_t enum contains
values for those 3 cases.
enum Grid_t {gi8, gi16, gi32}; //For 8, 16 and 32 bit uints.
Then I have this function that initializes and allocates one of this structs, and is supposed to return a pointer to the new struct.
mystruct* new(unsigned char foo, unsigned int bar, long value) {
mystruct* new;
new = malloc(sizeof(mystruct)); //Allocate space for the struct.
assert(new != NULL);
new->foo = foo;
new->max = bar;
int i;
switch(type){
case gi8: default:
new->data = (unsigned char *)calloc(new->max, sizeof(unsigned char));
assert(new->data != NULL);
for(i = 0; i < new->max; i++){
*((unsigned char*)new->data + i) = (unsigned char)value;
//Can I do anything with the format new->data[n]? I can't seem
//to use the [] shortcut to point to members in this case!
}
break;
}
return new;
}
The compiler returns no warnings, but I am not too sure about this method. Is it a legitimate way to use pointers?
Is there a better way©?
I missed calling it. like mystruct* P; P = new(0,50,1024);
Unions are interesting but not what I wanted. Since I will have to approach every specific case individually anyway, casting seems as good as an union. I specifically wanted to have much larger 8-bit arrays than 32-bits arrays, so an union doesn't seem to help. For that I'd make it just an array of longs :P
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,您不能取消引用
void*
指针,这是 C 语言标准所禁止的。在此之前,您必须将其转换为具体的指针类型。作为一种替代方案,根据您的需要,您还可以在结构中使用
union
而不是void*
:在任何给定时间,只有
data 之一.uc
、data.us
或data.ui
是有效的,因为它们都在内存中占用相同的空间。然后,您可以使用适当的成员来获取数据数组,而无需从void*
进行转换。No, you cannot dereference a
void*
pointer, it is forbidden by the C language standard. You have to cast it to a concrete pointer type before doing so.As an alternative, depending on your needs, you can also use a
union
in your structure instead of avoid*
:At any given time, only one of
data.uc
,data.us
, ordata.ui
is valid, as they all occupy the same space in memory. Then, you can use the appropriate member to get at your data array without having to cast fromvoid*
.这样一来
,根本就不需要施展了。只需使用
data_t
来确定您要访问哪个指针。What about
That way, there is no need to cast at all. Just use
data_t
to determine which of the pointers you want to access.type
应该是函数的参数吗? (不要命名这个函数或任何变量new
,否则任何试图使用它的 C++ 程序员都会追捕你)如果你想使用数组索引,你可以使用一个临时指针,如下所示
:真的不认为你的方法有问题。如果您期望特定的大小(我认为您确实给出了名称
gi8
等),我建议包括stdint.h
并使用 typedefsuint8_t、
uint16_t
和uint32_t
。Is
type
supposed to be an argument to the function? (Don't name this function or any variablenew
or any C++ programmer who tries to use it will hunt you down)If you want to use array indices, you can use a temporary pointer like this:
I don't really see a problem with your approach. If you expect a particular size (which I think you do given the name
gi8
etc.) I would suggest includingstdint.h
and using the typedefsuint8_t
,uint16_t
, anduint32_t
.指针只是内存空间中的一个地址。您可以选择按照您的意愿解释它。查看
union
以获取有关如何以多种方式解释同一内存位置的更多信息。指针类型之间的转换在 C 和 C++ 中很常见,并且使用 void* 意味着您不希望用户意外取消引用(取消引用 void* 将导致错误,但在转换为 int* 时取消引用同一指针则不会)
A pointer is merely an address in the memory space. You can choose to interpret it however you wish. Review
union
for more information on how you can interpret the same memory location in multiple ways.casting between pointer types is common in C and C++, and the use of void* implies that you dont want users to accidentally dereference (dereferencing a void* will cause an error, but dereferencing the same pointer when cast to int* will not)