I am working with a C project using visual studio. I tried to compile the following code:
void shuffle(void *arr, size_t n, size_t size)
{
....
memcpy(arr+(i*size), swp, size);
....
}
I get the following error with Visual studio Compiler:
error C2036: 'void *' : unknown size
The code compile well with GCC. How to solve this error?
asked May 26, 2016 at 12:15
ProEns08ProEns08
1,8362 gold badges21 silver badges38 bronze badges
6
You can’t perform pointer arithmetic on a void *
because void
doesn’t have a defined size.
Cast the pointer to char *
and it will work as expected.
memcpy((char *)arr+(i*size), swp, size);
answered May 26, 2016 at 12:20
dbushdbush
199k21 gold badges210 silver badges262 bronze badges
1
- Remove From My Forums
-
Question
-
Greetings,
I have a syntax similar to this :
void* data;
int number_to_increment;
data+= number_to_increment;
I think this is ok for GNU/GCC compiler, but how to do to make it working in MSVC?
Answers
-
«I think this is ok for GNU/GCC compiler»
I doubt that, this code is not supposed to be valid in C++:
«For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a
pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type»«The void type is an incomplete type that cannot be completed»
If GCC allows such code then it’s probably an extension of the language.
«but how to do to make it working in MSVC»
Normally you cast the void * to char *:
data = (char *)data + number_to_increment;
-
Marked as answer by
Thursday, September 5, 2013 9:27 AM
-
Marked as answer by
-
void* data;
int number_to_increment;
data+= number_to_increment;
When you increment a pointer the compiler must know the size of the object(s) to which
the pointer is pointing. It has to increment (or decrement) the address in the pointer
by the number of bytes that an object of that type occupies. Since a void pointer
contains the address of an object of unknown type and size, the compiler has no way of
«knowing» by how much to increment the address.One possible solution is to use a typecast so the compiler has an object of known size
with which to work.— Wayne
-
Marked as answer by
Yuri.B
Thursday, September 5, 2013 9:27 AM
-
Marked as answer by
Содержание
- Error c2036 void unknown size
- Answered by:
- Question
- Answers
- Error c2036 void unknown size
- Error c2036 void unknown size
- Answered by:
- Question
- Answers
- Error c2036 void unknown size
Error c2036 void unknown size
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Answered by:
Question
I have a syntax similar to this :
I think this is ok for GNU/GCC compiler, but how to do to make it working in MSVC?
Answers
«I think this is ok for GNU/GCC compiler»
I doubt that, this code is not supposed to be valid in C++:
«For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type»
«The void type is an incomplete type that cannot be completed»
If GCC allows such code then it’s probably an extension of the language.
Источник
Error c2036 void unknown size
Hello, i’m writing a function which sort a ‘void*’ array
using index numbers in ‘indArr’, and return a new, sorted, array.
This suppose to be a generic function that will work with any var. type.
The error i keep getting (on line 7):
I suppose I’m missing something important here.
Any guidance appreciated.
void pointers don’t have any attributes, no size, nothing so you can’t do anything with them except pass them around. If you want to use the data they point to then you have to cast them to a data type.
I’ve tried to explain with comments but if you don’t follow anything post a question
Hope this helps
Void is not a data-type.
You use void to declare a function that returns nothing.
so, you have to choose a suitable data-type (int, float, double, char etc.) to create an array.
Then, you can use a function void scramble( . ) with a pointer to that array to do whatever you wish to the array.
bnbertha
Your code doesn’t seem to work.
int main
I understand. The whole program looks like this:
So i need this function to work with any data type i throw at it.
Источник
Error c2036 void unknown size
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Answered by:
Question
I have the following function and when I compile it under VS.NET 2005, the following compile warnings show up:
Warning 1 warning C4311: ‘type cast’ : pointer truncation from ‘void *’ to ‘long’ c:temptestonelibutils.c 56
Warning 2 warning C4312: ‘type cast’ : conversion from ‘unsigned long’ to ‘void *’ of greater size c:temptestonelibutils.c 56
/*
* Dynamically allocate a 2d (x*y) array of elements of size _size_ bytes.
*/
void **MatrixIB (unsigned long x, unsigned long y, int size)
<
void *ptr;
void **returnPtr;
register unsigned long i, j;
returnPtr = (void **) malloc (x * sizeof(void *));
ptr = (void *) malloc (x * y * size);
for (i=0, j=0; j Compile Warnings
>
return ((void **) returnPtr);
> /* Matrix() */
I made the following modification
I> returnPtr[j] = (void *) (ptr + i); // Compile Errors
Error 1 error C2036: ‘void *’ : unknown size c:temptestonelibutils.c 57
2> returnPtr[j] = (void *) ((long*)ptr + i); //
3> returnPtr[j] = (void *) ((char*)ptr + i); //
I think the solution 3> should be the correct one.
If any, how can the original function works without errors if we just ignore the warning.
(i.e. Use returnPtr[j] = (void *) ((long)ptr + i); )
Based on the design of this function, which modification is right. Or, they are all wrong.
Thank you very much
Answers
You are getting warnings due to casting a void* to a type of a different size. On a 64-bit Windows computer, ‘long’ is a 32-bit type, and all pointers are 64-bit types. So, when you cast a (void*) to (long), you are losing 32 bits of data in the conversion. Losing bytes like this is called ‘truncation’, and that’s what the first warning is telling you. From that point on, you are dealing with 32 bits. However, you are also casting the result of this operation to (void*). Since all pointers on 64-bit Windows are 64 bits, you are growing the data size from 32 bits back to 64 bits. This is what the second warning is telling you. To avoid truncating your pointer, cast it to a type of identical size. You can use any other pointer, or you can use (size_t), which is 64 bits.
Even if you are compiling your program for a 32-bit computer, you should fix your code to remove these warnings, to ensure your code is easily portable to 64-bit.
Next, when doing pointer arithmetic, the addition operation will use the pointer’s type to determine how many bytes to add to it when incrementing it. For example, if you write ((int*)ptr + 1), it will add 4 bytes to the pointer, because «ints» are 4 bytes each. If you write ((char*)ptr + 1), it will advance the pointer 1 byte, because a «char» is 1 byte. The code ((void*)ptr + 1) does not work, because the compiler has no idea what size «void» is, and therefore doesn’t know how many bytes to add. This is why you got Error 1 C2036, from your post.
Since the ‘size’ argument for your function is the number of bytes each element in the array needs, I think casting the pointer to (char*) is appropriate. So, solution #3 works just fine.
Alternatively, if you choose to cast the ptr variable to (size_t) instead, then you don’t need to worry about the pointer type anymore. You could use this code, and it would do the same thing as casting ptr to (char*)
Источник
Error c2036 void unknown size
Есть указатель LPVOID на массив данных. Нужно кусочками перекладывать данные из этого массива в массив другого типа (для передачи). Т.е. имеем:
пробовал делать так:
error C2036: ‘void *’ : unknown size
Как мне тут быть?
P.S. Первый массив имеет весьма большой размер.
От: | Nuald | http://nuald.blogspot.com | |
Дата: | 21.06.04 05:08 | ||
Оценка: |
Здравствуйте, Silverj, Вы писали:
S>
Прежде чем использовать левые примеры, постарайтесь сначала разобраться, как они работают.
От: | Silverj | |
Дата: | 21.06.04 05:18 | |
Оценка: |
Здравствуйте, Nuald, Вы писали:
N>
N>Прежде чем использовать левые примеры, постарайтесь сначала разобраться, как они работают.
Это все замечательно, но как мне скопировать следующие 255 байт из буфера. Т.е. как организовать что то вроде
Вся загвоздка как раз в этом
От: | Nuald | http://nuald.blogspot.com | |
Дата: | 21.06.04 05:57 | ||
Оценка: |
Здравствуйте, Silverj, Вы писали:
S>Это все замечательно, но как мне скопировать следующие 255 байт из буфера. Т.е. как организовать что то вроде
S>
S>Вся загвоздка как раз в этом
От: | aka50 | |
Дата: | 21.06.04 06:09 | |
Оценка: | -2 |
Здравствуйте, Silverj, Вы писали:
В Вашем случае попытка получить 256 элемент «массива» типа LPVOID (через []), но компилятор не знает,
что такое VOID и чему равен размер void (например для char — этом может быть 1 byte, для int может быть 4),
по этому попытка взятия адреса не работает.
От: | Вадим Никулин | Здесь | |
Дата: | 21.06.04 07:31 | ||
Оценка: | +1 |
Здравствуйте, aka50, Вы писали:
[]
Ни один из этих примеров не прокатит
A>В Вашем случае попытка получить 256 элемент «массива» типа LPVOID (через []), но компилятор не знает,
A>что такое VOID и чему равен размер void (например для char — этом может быть 1 byte, для int может быть 4),
A>по этому попытка взятия адреса не работает.
Не работает индексация, а не взятие адреса. Не работает по тем причинам, которые описали Вы.
Решение — привести к типу BYTE (ну, или char).
От: | aka50 | |
Дата: | 21.06.04 08:43 | |
Оценка: |
Здравствуйте, Вадим Никулин, Вы писали:
ВН>Здравствуйте, aka50, Вы писали:
ВН>[]
ВН>Ни один из этих примеров не прокатит
A>>В Вашем случае попытка получить 256 элемент «массива» типа LPVOID (через []), но компилятор не знает,
A>>что такое VOID и чему равен размер void (например для char — этом может быть 1 byte, для int может быть 4),
A>>по этому попытка взятия адреса не работает.
ВН>Не работает индексация, а не взятие адреса. Не работает по тем причинам, которые описали Вы.
ВН>Решение — привести к типу BYTE (ну, или char).
угу. неправильно написал. Вообще-то я «типа LPVOID (через []), но компилятор не знает, что такое VOID и чему равен размер void» — это я так криво хотел сказать то-же самое
по поводу «не будет работать». по моему голословно. примеры пожлста. Вот мои
От: | Вадим Никулин | Здесь | |
Дата: | 21.06.04 10:50 | ||
Оценка: |
Здравствуйте, aka50, Вы писали:
A>Здравствуйте, Вадим Никулин, Вы писали:
A>по поводу «не будет работать». по моему голословно. примеры пожлста. Вот мои
A>
Здесь buf имеет тип char[]. Так действительно будет работать. В Вашем примере типы buf и lpBuf не указаны. Если брать типы такими же, как в исходном посте, то строка
не скомпилируется. В остальных примерах, типа
идет копирование из конца буфера в начало. Компилироваться, конечно, будет, но автор вопроса, мне кажется, хотел нечто другое.
От: | aka50 | |
Дата: | 21.06.04 10:56 | |
Оценка: |
Здравствуйте, Вадим Никулин, Вы писали:
ВН>Здесь buf имеет тип char[]. Так действительно будет работать. В Вашем примере типы buf и lpBuf не указаны. Если брать типы такими же, как в исходном посте, то строка
угу. согласен. ИМХО автор некорректно задал вопрос. Он не указал ни язык ни платформу (хотя можно конечно догадаться, что Win32/C++). Под C будет работать в любом случае. И с char* и c unsgined char*. Под С++ — нет. (это я проглядел).
От: | Silverj | |
Дата: | 22.06.04 05:44 | |
Оценка: |
Спасибо всем за ответы, но наверно тему можно закрывать, т.к. все мои проблемы разрешил еще Nuald. Сделал следующим образом:
Источник
- Forum
- Beginners
- ‘void *’ : unknown size
‘void *’ : unknown size
Hello, i’m writing a function which sort a ‘void*’ array
using index numbers in ‘indArr’, and return a new, sorted, array.
This suppose to be a generic function that will work with any var. type.
The error i keep getting (on line 7):
|
|
the code:
|
|
I suppose I’m missing something important here.
Any guidance appreciated.
Last edited on
void pointers don’t have any attributes, no size, nothing so you can’t do anything with them except pass them around. If you want to use the data they point to then you have to cast them to a data type.
|
|
I’ve tried to explain with comments but if you don’t follow anything post a question
Hope this helps
Bertha
Void is not a data-type.
You use void to declare a function that returns nothing.
so, you have to choose a suitable data-type (int, float, double, char etc.) to create an array.
Then, you can use a function void scramble( …) with a pointer to that array to do whatever you wish to the array.
int main
bnbertha
Your code doesn’t seem to work…
int main
I understand. The whole program looks like this:
|
|
So i need this function to work with any data type i throw at it.
Last edited on
If you want to work with any data-type, you should use a template function instead.
It does work, you need p to be an int ptr though to be able to see it.
|
|
However, as Zaita pointed out, this is a ‘C’ solution, the C++ solution would be to use a template
Last edited on
Yeah, I’m writing this in C, thank you!
Topic archived. No new replies allowed.
I am working with a C project using visual studio. I tried to compile the following code:
void shuffle(void *arr, size_t n, size_t size)
{
....
memcpy(arr+(i*size), swp, size);
....
}
I get the following error with Visual studio Compiler:
error C2036: 'void *' : unknown size
The code compile well with GCC. How to solve this error?
But you are sure that you are compiling with a C compiler?
– terence hill
However you cannot index pointer of type void. You can try to cast it to char so that each increment is of one byte
– terence hill
Because the compiler does not know what size a void*
pointer is, although there could be GCC extension that permits it. To do pointer arithmetic, you have to know the size of the data it points to. Note that adding 1
to a pointer to a 32-bit int
will add 4
to the pointer itself. Just like with array indexing, where you access the second element with arr[1]
not with arr[4]
.
– Weather Vane
Thanks all for your interesting remarks.
– ProEns08
- Forum
- General Programming Boards
- C Programming
- typecasting void *pointers
-
07-02-2006
#1
Registered User
typecasting void *pointers
Code:
int a[2] = {0,1}; void *b; b = (int *)&a; b++; printf("a's address: %pn", b);
Hi all, i typecasted the void pointer and try to increment (b++) it to point to the next address but there is this error: «error C2036: ‘void *’ : unknown size».
Can someone give me some advise on this problem.
-
07-02-2006
#2
Lurking
You typecasted a not b. This is correct.
-
07-02-2006
#3
ATH0
No actually neither one of you are right. You never have to typecast assignments to void pointers. What it is complaining about is you incrementing b, not assigning it a value.gcc gives a warning about lvalue casts being depreciated, but in this case, it’s wrong.
Quzah.
Hope is the first step on the road to disappointment.
-
07-02-2006
#4
and the hat of int overfl
I’m sure someone will be along with the right answer eventually.
Hint: consider what sizeof(void) means.
-
07-02-2006
#5
Registered User
Code:
int a[2] = {0,1}; void *b; b = &a; ((int*)b)++; printf("a's address: %pn", b);
Thanks guys, i know that the problem is about the incrementing b , and i tried before but it still couldn’t work: «error C2105: ‘++’ needs l-value».
-
07-02-2006
#6
ATH0
Originally Posted by Salem
I’m sure someone will be along with the right answer eventually.
Hint: consider what sizeof(void) means.
I’ll assume you’re not talking about my post. If so, what’s the correct way? This works just fine, according to a pedantic-ansi-GCC.
Code:
#include<stdio.h> int main( void ) { int a[] = { 1, 2 }; void* b; b = a; ((int*)b)++; printf( "%dn", *(int*)b ); return 0; } gcc -o inc inc.c -Wall -pedantic -ansi inc.c: In function `main': inc.c:8: warning: use of cast expressions as lvalues is deprecated ./inc 2
Quzah.
Hope is the first step on the road to disappointment.
-
07-02-2006
#7
and the hat of int overfl
> «error C2036: ‘void *’ : unknown size».
char *p ; p++;
This advances p through memory by sizeof(char) bytesint *p; p++;
This advances p through memory by sizeof(int) bytesNow, given that void has no size, what do you expect
void *p ; p++
to do?
void has no size (that’s what the error message says), so the compiler doesn’t know what to add.> b = &a;
Do you know the difference between this, and say
b = a;
b = &a[0];I bet you tried this somewhere along the line, and got yet another error message.
int *b;
b = &a; // wrong
But rather than fixing it, you reached for void* as some magic cure-all.How about
Code:
int a[2] = {0,1}; int *b; b = a; b++; printf("a's address: %pn", b);
-
07-02-2006
#8
Registered User
Hi Salem, appreciated the help. I was actually trying out the use of void pointers. You see, i actually need to process a array in terms of int then char:
Code:
int a[2] = {0,1}; void *b; b = a; // do some processing ((int*)b)++; ((char*)b)++; // do some processing ((char*)b)++; // do some processing ((char*)b)++; // do some processing ((char*)b)++; // do some processing
As for
int *b;
int a[2] = {1,0};
>b = a;
>b = &a[0];I believe b is pointing to the 1st int member in a’s array.
-
07-02-2006
#9
Registered User
In that case, Eavan, I suggest it is unnecessary to mess around with a void pointer;
Code:
int a[2] = {0,1}; char *b; b = a; // do some processing *((int *)b) = 42; // Example; sets first int to 42 b += sizeof(int); ++b; // do some processing ++b; // do some processing ++b; // do some processing ++b; // do some processing
Makes it a bit more obvious what you’re doing, without having to jump through as many hoops with conversions.
-
07-02-2006
#10
Registered User
How about
b = (&a) [+1]
-
07-02-2006
#11
Devil’s Advocate
Originally Posted by puppy
How about
b = (&a) [+1]
I don’t get it.
-
07-02-2006
#12
Registered User
Sorry …
Your original program compiles fine (gcc version 4.1.0)
I have taken the liberty to slightly modify your prog toCode:
#include <stdio.h> int main() { int a[2] = {0,1}; void *b; b = (int *)&a; b++; printf("a's address: %pn", &a); printf("b's address: %pn", b); }
the o/p is
a’s address: 0xbfdf66a8
b’s address: 0xbfdf66a9
so the address has been incremented by 1 byte …(in this case from 8 to 9)
-
07-02-2006
#13
and the hat of int overfl
> Your original program compiles fine (gcc version 4.1.0)
Apparently, you need to add more compiler options to prevent you relying on all sorts of compiler extensionsCode:
$ gcc bar.c $ gcc -W -Wall -ansi -pedantic -O2 bar.c bar.c: In function �main�: bar.c:10: warning: wrong type argument to increment bar.c:12: warning: format �%p� expects type �void *�, but argument 2 has type �int (*)[1u]� bar.c:14: warning: control reaches end of non-void function
Yes, it does «compile fine» if you have a lazy approach to diagnosing potential problems,
-
07-02-2006
#14
Registered User
sorry ..
I used make bar
therefor no errors ?
-
07-02-2006
#15
Registered User
Originally Posted by puppy
sorry ..
I used make bar
therefor no errors ?Possibly. But makefiles are just plain text and can be adjusted.
Kurt
Popular pages
- Exactly how to get started with C++ (or C) today
- C Tutorial
- C++ Tutorial
- 5 ways you can learn to program faster
- The 5 Most Common Problems New Programmers Face
- How to set up a compiler
- 8 Common programming Mistakes
- What is C++11?
- Creating a game, from start to finish
Recent additions
- How to create a shared library on Linux with GCC — December 30, 2011
- Enum classes and nullptr in C++11 — November 27, 2011
- Learn about The Hash Table — November 20, 2011
- Rvalue References and Move Semantics in C++11 — November 13, 2011
- C and C++ for Java Programmers — November 5, 2011
- A Gentle Introduction to C++ IO Streams — October 10, 2011
Similar Threads
-
Replies: 31
Last Post: 09-05-2008, 01:01 AM
-
Replies: 4
Last Post: 03-27-2007, 01:10 AM
-
Replies: 13
Last Post: 12-26-2006, 04:17 PM
-
Replies: 6
Last Post: 07-01-2004, 05:40 AM
-
Replies: 29
Last Post: 08-25-2003, 11:58 AM
Приведенный ниже код компилируется, хотя я ожидал, что компилятор пожалуется, что он не знает размер Foo
, Однако, если я заменю #include
с предварительной декларацией Bar
по этой причине не компилируется.
я знаю это Foo
определенно только вперед объявлен, потому что если Foo* myfoo;
изменено на Foo myfoo;
тогда это не компилируется. Почему эта ошибка возникает только с вектором объектов одного типа, а не с другим?
Использование Visual Studio Express 2013.
#include "Bar.h"class Foo;
class MyClass{
Foo* myfoo;
std::vector<Foo> foos;
std::vector<Bar> bars;
};
-1
Решение
Сами по себе нет причин, по которым аргументы типа шаблона должны быть полными типами (фактически, 14.3.1 / 2 прямо заявляет, что это не так).
Такое требование тогда исходит из того, как этот тип используется в определении шаблона вашего типа (в данном случае, std::vector
). Например, [C++11: 20.7.1/5]
утверждает, что аргумент шаблона T
из std::unique_ptr<T>
может быть неполным в точке unique_ptr
декларация; это указано явно, потому что это было не случай для std::auto_ptr
.
Вы найдете это, как только вы попытаетесь делать почти все с вашим вектором, вам понадобится T
быть завершенным. Эта проблема обнаруживается во время компиляции, так как все сводится к созданию шаблонов, поэтому ваш компилятор будет делать соответствующие ошибки по мере необходимости.
Деструктор вектора обычно является одной из таких вещей.
Так, используя GCC 4.8, я не могу создать экземпляр или вектор с неполным value_type
:
#include <vector>
class Foo;
class Bar;
std::vector<Foo> foos;
std::vector<Bar> bars;
int main() {}
ошибка: недопустимое использование неполного типа ‘class Foo’
ошибка: недопустимое использование неполного типа ‘класс Bar’
Только когда я использую их в качестве членов в классе, который никогда не используется вся вещь компилируемая, потому что деструкторы векторов никогда не вызываются и, следовательно, никогда не создаются экземплярами шаблона:
#include <vector>
class Foo;
class Bar;
class T
{
std::vector<Foo> foos;
std::vector<Bar> bars;
};
int main() {}
(Нет ошибок)
Что бы ваша реализация ни делала, она будет одинаковой для обоих Foo
а также Bar
; если вы видите разницу между ними, то вы должны делать что-то другое с Bar
что вы нам не показали.
2
Другие решения
(Я знаю, что он уже ответил, но я собираюсь опубликовать мой в любом случае)
Хороший способ думать об этом — когда нужно знать определение класса? В случае vector<Foo>
, sizeof(Foo)
должен быть известен в резервное время или время доступа, а информация о Foo :: constructor и Foo :: destructor должна быть известна, когда мы добавляем или удаляем элементы в векторе. И, конечно, для уничтожения вектора нужен Foo :: destructor.
Так что это приводит к одной из наиболее распространенных проблем с объявленными вперед аргументами шаблона для std :: vector: у вас есть класс выше, который использует конструктор по умолчанию а также деструктор по умолчанию. Когда определяется деструктор по умолчанию? Ну (семантически, по крайней мере) он определен, когда вы не определяете его в классе, поэтому он определен в этом заголовочном файле. Более того, что в этом деструкторе? В каждом деструкторе C ++ скрыт код очистки, выходящий за пределы тела деструктора: он вызывает все деструкторы всех членов … но это означает, что он пытается вызвать деструктор для std :: vector.
Ты SOL? Нету. Следующее должно работать просто отлично для вас.
//myclass.hpp
class Foo;
class Bar;
class MyClass{
public:
MyClass();
~MyClass();
Foo* myfoo;
std::vector<Foo> foos;
std::vector<Bar> bars;
private:
};
//myclass.cpp
#include "myclass.hpp"#include "Bar.h"#include "Foo.h"MyClass::MyClass(){};
MyClass::~MyClass(){};
1