I have the need to allocate memory for an array of pointers to structs. The documentation for malloc()
informs that the return from this function returns a pointer to the first block of memory that was allocated. Well, in my case I called the function like this:
我有必要为一组指向结构的指针分配内存。malloc()的文档指出,这个函数的返回返回返回一个指向被分配的第一个内存块的指针。在我的例子中,函数是这样的
malloc(SIZE_TABLE*sizeof(struct structName*))
malloc(SIZE_TABLE * sizeof(struct structName *))
The problem being that, since malloc returns a pointer to this memory (containing pointers), it will thus return a 2-star pointer of type structName
.
问题是,由于malloc返回一个指向该内存的指针(包含指针),因此它将返回一个2-star的structName类型指针。
Instead of having an extra line to assign the 2-star pointer and then dereference it, can you dereference the call itself?
而不是有一个额外的线来分配2星指针然后取消它,你能取消这个调用本身吗?
Instead of:
而不是:
struct structName** temp = malloc(SIZE_TABLE*sizeof(struct structName*))
struct structName** temp = malloc(SIZE_TABLE*sizeof(struct structName*))
struct structName* temp2 = *(temp);
结构体名称* temp2 = *(temp);
Could you do something like:
你能做点什么吗?
struct structName* temp2 = *( malloc(SIZE_TABLE*sizeof(struct structName*)) );
struct structName* temp2 = *(malloc(SIZE_TABLE*sizeof(struct structName*));
I have done little when it comes to 2-star pointers, so if there is a better way to approach this problem (or if I am simply miss-understanding it all), please let me know.
当涉及到2星指针时,我几乎没有做过什么,所以如果有更好的方法来解决这个问题(或者如果我只是理解错误),请告诉我。
4 个解决方案
#1
5
No you can not do that directly.
不,你不能直接这么做。
malloc
returns void*
, dereferencing a void*
is undefined, and it will generate a compiler warning.
But you can cast it to different pointer type and then dereference.
The following may work:
malloc返回void*,取消对void*的引用没有定义,它将生成一个编译器警告。但是您可以将它转换为不同的指针类型,然后取消引用。以下工作:
struct structName* temp2 = *((struct structName**)malloc(SIZE_TABLE*sizeof(struct structName*)));
But this is a serious memory leak as the original return value of malloc
is lost and is not good practice at all as you are not sure about the return value of malloc
. If it is NULL
dereferencing is not possible.
但是这是一个严重的内存泄漏,因为malloc的原始返回值丢失了,并且不是很好的实践,因为您不确定malloc的返回值。如果是空取消引用是不可能的。
There is another problem in doing that. The value at the address returned by malloc
is uninitialized, so dereferencing it after casting also lead to undefined behavior.
这样做还有一个问题。malloc返回的地址的值未初始化,因此在强制转换后取消引用也会导致未定义的行为。
Always check for NULL
before dereferencing any pointer. and
Always save the return value of malloc
to free
it later.
在取消引用任何指针之前,总是要检查NULL。并且始终保存malloc的返回值以便稍后释放它。
#2
3
No you can't. This is because the return value of malloc
is void *
, and it is not known that to which type this void *
get converted in this case. Dereferencing a void *
invokes undefined behavior.
不,你不能。这是因为malloc的返回值为void *,在这种情况下,不知道这个void *转换到哪个类型。撤销无效引用*调用未定义的行为。
You will also get a warning in most compiler if you do so e.g. for GCC
如果你这样做,你也会在大多数编译器中得到警告
warning: dereferencing ‘void *’ pointer [enabled by default]
I would not suggest you to cast the return value of malloc
and then dereference it. Better to stick with your first approach.
我不建议您先设定malloc的返回值,然后再取消它的引用。最好坚持你的第一个方法。
#3
2
As others have said, you can dereference it if you add a type cast. But you shouldn't. One reason already mentioned is checking for NULL
. The other is:
正如其他人所说,如果添加类型转换,您可以取消它。但是你不应该。已经提到的一个原因是检查NULL。另一种是:
- you always have to save the pointer that
malloc
returns in order to be able to free the memory later. - 您必须保存malloc返回的指针,以便以后能够释放内存。
#4
1
You need to keep in mind that your malloc allocates SIZE_TABLE pointers to struct structName
, but these struct structName
are not allocated. Even worse: the buffer allocated by malloc is not initialized, so none of the pointers is initialized/valid.
您需要记住,您的malloc将SIZE_TABLE指针分配给struct structName,但是这些struct structName没有被分配。更糟糕的是:malloc分配的缓冲区没有初始化,因此没有一个指针是初始化的/有效的。
What you need to do:
你需要做的:
struct structName ** table = malloc(SIZE_TABLE*sizeof(struct structName*));
size_t i;
for(i = 0; i < SIZE_TABLE; ++i)
table[i] = malloc(sizeof(struct structName));
What you propose:
你的建议:
struct structName * tableEntryAtIndex0 = malloc(SIZE_TABLE*sizeof(struct structName*));
This does not compile, you cannot dereference a void *
.
这不会编译,您不能取消引用一个void *。
Either of these two lines would compile:
这两行任何一行都可以汇编:
// Either the way you wanted it
struct structName * tableEntryAtIndex0 = *((struct structName **)malloc(SIZE_TABLE*sizeof(struct structName*)));
// Or with an index to punctuate that a table was malloc-ed (in my opinion better to understand what happens)
struct structName * tableEntryAtIndex0 = ((struct structName **)malloc(SIZE_TABLE*sizeof(struct structName*)))[0];
This still has two problems: first you are losing the pointer to the overall table. So you cannot check it for NULL, you cannot access any other table entry and you cannot free the memory. Second the table was not initialized by malloc, so you are getting a garbage pointer. Now setting tableEntryAtIndex0 to malloc(sizeof(struct structName))
would not help, because this would just modify tableEntryAtIndex0 and not the entry in the table.
这仍然有两个问题:首先,您将丢失指向整个表的指针。所以不能检查它是否为NULL,不能访问任何其他表条目,也不能释放内存。第二,表没有被malloc初始化,因此您将获得一个垃圾指针。现在,将tableEntryAtIndex0设置为malloc(sizeof(struct structName))是没有用的,因为这只会修改tableEntryAtIndex0而不是表中的条目。
#1
5
No you can not do that directly.
不,你不能直接这么做。
malloc
returns void*
, dereferencing a void*
is undefined, and it will generate a compiler warning.
But you can cast it to different pointer type and then dereference.
The following may work:
malloc返回void*,取消对void*的引用没有定义,它将生成一个编译器警告。但是您可以将它转换为不同的指针类型,然后取消引用。以下工作:
struct structName* temp2 = *((struct structName**)malloc(SIZE_TABLE*sizeof(struct structName*)));
But this is a serious memory leak as the original return value of malloc
is lost and is not good practice at all as you are not sure about the return value of malloc
. If it is NULL
dereferencing is not possible.
但是这是一个严重的内存泄漏,因为malloc的原始返回值丢失了,并且不是很好的实践,因为您不确定malloc的返回值。如果是空取消引用是不可能的。
There is another problem in doing that. The value at the address returned by malloc
is uninitialized, so dereferencing it after casting also lead to undefined behavior.
这样做还有一个问题。malloc返回的地址的值未初始化,因此在强制转换后取消引用也会导致未定义的行为。
Always check for NULL
before dereferencing any pointer. and
Always save the return value of malloc
to free
it later.
在取消引用任何指针之前,总是要检查NULL。并且始终保存malloc的返回值以便稍后释放它。
#2
3
No you can't. This is because the return value of malloc
is void *
, and it is not known that to which type this void *
get converted in this case. Dereferencing a void *
invokes undefined behavior.
不,你不能。这是因为malloc的返回值为void *,在这种情况下,不知道这个void *转换到哪个类型。撤销无效引用*调用未定义的行为。
You will also get a warning in most compiler if you do so e.g. for GCC
如果你这样做,你也会在大多数编译器中得到警告
warning: dereferencing ‘void *’ pointer [enabled by default]
I would not suggest you to cast the return value of malloc
and then dereference it. Better to stick with your first approach.
我不建议您先设定malloc的返回值,然后再取消它的引用。最好坚持你的第一个方法。
#3
2
As others have said, you can dereference it if you add a type cast. But you shouldn't. One reason already mentioned is checking for NULL
. The other is:
正如其他人所说,如果添加类型转换,您可以取消它。但是你不应该。已经提到的一个原因是检查NULL。另一种是:
- you always have to save the pointer that
malloc
returns in order to be able to free the memory later. - 您必须保存malloc返回的指针,以便以后能够释放内存。
#4
1
You need to keep in mind that your malloc allocates SIZE_TABLE pointers to struct structName
, but these struct structName
are not allocated. Even worse: the buffer allocated by malloc is not initialized, so none of the pointers is initialized/valid.
您需要记住,您的malloc将SIZE_TABLE指针分配给struct structName,但是这些struct structName没有被分配。更糟糕的是:malloc分配的缓冲区没有初始化,因此没有一个指针是初始化的/有效的。
What you need to do:
你需要做的:
struct structName ** table = malloc(SIZE_TABLE*sizeof(struct structName*));
size_t i;
for(i = 0; i < SIZE_TABLE; ++i)
table[i] = malloc(sizeof(struct structName));
What you propose:
你的建议:
struct structName * tableEntryAtIndex0 = malloc(SIZE_TABLE*sizeof(struct structName*));
This does not compile, you cannot dereference a void *
.
这不会编译,您不能取消引用一个void *。
Either of these two lines would compile:
这两行任何一行都可以汇编:
// Either the way you wanted it
struct structName * tableEntryAtIndex0 = *((struct structName **)malloc(SIZE_TABLE*sizeof(struct structName*)));
// Or with an index to punctuate that a table was malloc-ed (in my opinion better to understand what happens)
struct structName * tableEntryAtIndex0 = ((struct structName **)malloc(SIZE_TABLE*sizeof(struct structName*)))[0];
This still has two problems: first you are losing the pointer to the overall table. So you cannot check it for NULL, you cannot access any other table entry and you cannot free the memory. Second the table was not initialized by malloc, so you are getting a garbage pointer. Now setting tableEntryAtIndex0 to malloc(sizeof(struct structName))
would not help, because this would just modify tableEntryAtIndex0 and not the entry in the table.
这仍然有两个问题:首先,您将丢失指向整个表的指针。所以不能检查它是否为NULL,不能访问任何其他表条目,也不能释放内存。第二,表没有被malloc初始化,因此您将获得一个垃圾指针。现在,将tableEntryAtIndex0设置为malloc(sizeof(struct structName))是没有用的,因为这只会修改tableEntryAtIndex0而不是表中的条目。