I’m getting an «invalid use of void expression» error regarding the following function:
void remove_data(char* memory, char* bitmap, int pos)
{
int i;
i = (int)test_bit(bitmap, pos-1);
if(i != 0)
{
memory[pos-1] = NULL;
toggle_bit(bitmap, pos-1);
}
}
Now from what I’ve read on other threads regarding this similar issue this error pops up when the programmer uses something within the function that will generate an output. However, I’m failing to see what would cause that in the code I’ve written.
Edit to add:
The toggle bit function used in it is also type void and doesn’t return a value.
void test_bit(char * bitmap, int pos)
{
int bit;
bit = bitmap[pos/8] & (1<<(pos%8));
printf("%dn", &bit);
}
I commented the printf line in test_bit but the error is still there.
asked Oct 8, 2012 at 16:55
KaliKali
291 gold badge1 silver badge3 bronze badges
6
However, I’m failing to see what would cause that in the code I’ve written.
Me too, because I don’t think you have posted the relevant code. Regardless, I think this is probably your problem:
i = (int)test_bit(bitmap, pos-1);
Please show us the signature for test_bit
. I’m guessing it returns void
or you have forward declared it somewhere and accidentally wrote:
void test_bit(char*, int);
Since the function returns void
(i.e., nothing) you cannot then proceed to cast the return value (which is nothing) to an int
as you are doing, it makes no sense and is illegal.
EDIT: You have verified in the comments that test_bit
is in fact declared to return void
, so that’s your problem.
answered Oct 8, 2012 at 16:58
Ed S.Ed S.
122k21 gold badges181 silver badges262 bronze badges
Since test_bit is void, you may not use its return (as in i = (int)test_bit(bitmap, pos-1);
) — there is no return value.
answered Oct 8, 2012 at 16:59
mahmah
38.8k9 gold badges75 silver badges93 bronze badges
Obvious Solution: Don’t assign results of function returning void.
Non-Obvious Solution: Don’t nest function calls, and you are less likely
to be looking in all of the wrong spots, thinking the compiler is broken.
#include <stdio.h> //:for: printf(...)
void YOUR_MISTAKE_ACTUALLY_HERE();
void MyFunc( void );
void* WRAPPED_MyFunc( int, int, int );
int main( void ){
printf("[BEG:main]n");
void* HW = NULL;
HW = WRAPPED_MyFunc( //:<---So you check this, but it looks fine.
1
, YOUR_MISTAKE_ACTUALLY_HERE()
, 3
);; //:<--- compiler says "Invalid Use Of Void Expression" Here.
if( HW ){ /** NOOP **/ };
printf("[END:main]n");
}
void YOUR_MISTAKE_ACTUALLY_HERE(){ }
//:Pretend this function is fetched from DLL.
//:Casting all DLL functions initially to void(*pfn)void
//:in a lookup table, then re-casting later.
void MyFunc( void ){
return;
}//[;]//
typedef
void*
(* MyFunc_TYPEDEF)(
int a
, int b
, int c
);
void*
WRAPPED_MyFunc(
int a
, int b
, int c
){
MyFunc_TYPEDEF
fun =( MyFunc_TYPEDEF)
MyFunc;
void* ret=( fun(
a
, b
, c
));
return(
(void*)
ret
);;
}//:Func
answered Dec 9, 2019 at 3:39
KANJICODERKANJICODER
3,47729 silver badges16 bronze badges
You wrote
i = (int)test_bit(bitmap, pos-1);
Why have a cast?
Seems a bit wrong when the function is
void test_bit(char * bitmap, int pos)
{
int bit;
bit = bitmap[pos/8] & (1<<(pos%8));
printf("%dn", &bit);
}
You can’t convert a void into an integer.
Dharman♦
29.3k21 gold badges80 silver badges131 bronze badges
answered Oct 8, 2012 at 17:05
Ed HealEd Heal
58.6k17 gold badges87 silver badges125 bronze badges
0
Good question!
There is nothing special about void **
. It’s just a pointer which yields an lvalue of type void *
when it is dereferenced. It is not compatible with int **
.
The standard says you can convert any pointer into a void pointer and then back to a compatible one, e.g.
int x, *p = &x;
void *q = p;
const char *c = q;
int *d = q;
is allowed, because we convert q
back to compatible pointer, and something similar happens e.g. in a naive implementation of memcpy(3)
.
However, the standard doesn’t promise that pointers of different type have comparable representations, so it’s technically possible that the bit pattern of p
and q
are different, and when converting to and from a void pointer more than copying happens. For this reason when you do
*(void **)p = malloc(...);
it’s not certain that x
contains a valid address to an int
. Do you see how this is different from the suggestion from the F.A.Q.? On any platform I can think of this will probably work, but you never know how future compiler versions might optimize code like that. Beside all that, I fear that an API like that is error prone, because it will literally accept any pointer, not just pointers to pointers.
I’m defining an attachinterrupt and I’m running into an error. The line in question is:
void setup() {
attachInterrupt(digitalPinToInterrupt(stallsense1), changedirection(1), RISING);
attachInterrupt(digitalPinToInterrupt(stallsense2), changedirection(2), RISING);
}
and the error I’m getting is:
error: invalid use of void expression
attachInterrupt(digitalPinToInterrupt(stallsense2), changedirection(2), RISING);
^
exit status 1
invalid use of void expression
The idea is I have one function changedirection and two possible inputs, either 1 or 2.
I believe the issue is where I’ve called the function changedirection(1). I want to simply tell attachinterrupt to call the function changedirection with an input of either 1 or 2. How would I do this?
jsotola
1,2142 gold badges10 silver badges18 bronze badges
asked Jun 17, 2021 at 22:58
attachInterrupt
expects a simple pointer to function taking no arguments and returning nothing (void).
So, really there’s no way to directly do what you’re talking about. There’s no currying ability builtin. You can define your own functions like
void proxy_changedirection_1() {
changedirection(1);
}
And then attachInterrupt
specifying proxy_changedirection_1
, or you can use a lambda with no captures for the same purpose:
attachInterrupt(
digitalPinToInterrupt(stallsense1),
[] () {
changedirection(1);
},
RISING
);
answered Jun 17, 2021 at 23:17
timemagetimemage
4,6211 gold badge10 silver badges24 bronze badges
1
What happened is you wrote a void expression where an expression of type ‘pointer to function of void returning void’ (i.e., no arguments and no return value), was expected. The name of a function with no parentheses for an argument list is an expression of type ‘pointer to function’ taking whatever arguments & types that named function was declared to expect, and returning whatever type that named function was declared to return.
But if you write the parentheses with it, now you’ve written an expression that 1) would (if it were valid) get evaluated during the call to attachInterrupt() — much earlier that you want it to be! — and return a value of that return type rather than the type you expected.
@timemage has offered two ways to solve this.
answered Jun 17, 2021 at 23:34
JRobertJRobert
14.7k3 gold badges19 silver badges49 bronze badges
- Remove From My Forums
-
Question
-
Hello all:
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 56Code Snippet
/*
* 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<x; i+=(y*size), j++)
{
returnPtr[j] = (void *) ((long)ptr + i); // <<< 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); // <<< No compile errors
3> returnPtr[j] = (void *) ((char*)ptr + i); // <<< No compile errors
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
-Daniel
Answers
-
Hello Daniel,
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*)
returnPtr[j] = (void*)((size_t)(ptr) + i);
I hope that helps!
Сообщение от doka
а покажи как вызываешь?
Локализуй ошибку:
Сделай Sub CrPMailTest() и вызови её. Если ошибку не выдаст, то добавляй по-одному парамметры (Sub CrPMailTest(txt As String); Sub CrPMailTest(subj As String, txt As String))
вызов делаю так Call CrPMail(doc,who$,whoserver$,subj$,txt$), передаваемые параметры и их значения я попытался описать в первом посте. Сама функция отрабатывает на одном сервере в домене A, но на другом, в другом домене Б, где стоит не связанная реплика (одностороняя репликация из A в Б ) у некоторых пользователей (домена Б) выводит такую ошибку (сказать что у всех не могу), склоняюсь к предположению Morpheus, такое впечатление не хватает доступа у пользователя для вызова. Проверить толком не могу ограничен там в правах, кстати оба модуля подписал своей учеткой, может в этом проблема.
Сервер Win на оси 2003 , но действительно использую в subj$ конструкцию Chr$(10)+Chr$(13).
Пробовал сам в домене Б выполнить эту конструкцию, получаю ошибку, в A делаю все ок.
Для Kee_Keekkenen
ошибок компиляции нету, я же написал что в одном случае все работает на ура, мусора тоже нет, уже шаманил с полным пересозданием модулей, пока результатов нет. Считаю. что права тянут.
Что в плане прав можно проверить у моей учетки в домене B, какой минимум необходим для успешного выполнения ?