What Does (void *) Mean When Used To Set The Arguments For A Function
Maybe your like
This is probably more a "C language" question than something that is Arduino-specific but I still don't understand it as my extensive programming experience involves little exposure to this group of languages.
I have been trying to learn about the Arduino timer and I notice that functions that are called by timers are often defined with this type of argument and all works fine when used in this manner. However, I have tried to call such a function in a simple call not involving timers and I can't work out what to include as the argument in the call. I have tried nothing, a boolean variable and a few other things and can't get past compile.
UKHeliBob January 12, 2022, 7:29am 2Please post an example sketch that illustrates your question so that it can be seen in context
downibri January 12, 2022, 8:33am 3This compiles (and works).
// Include necessary library files #include <ESP8266WiFi.h> #include <arduino-timer.h> // Timer objects auto OutputTimer = timer_create_default(); void setup () { // Call CT read function once per minute. OutputTimer.every(60000, ReadCT); } void loop() { OutputTimer.tick(); } bool ReadCT(void *) { Serial.println( "Entered ReadCT" ); // Call current transformer reader and send reading to server return true; }When I try and add an extra call to ReadCT in front of the timer-based one
... bool bolJunk; void setup () { // Call CT read function once per minute. bolJunk = ReadCT(); OutputTimer.every(10000, ReadCT); ...I can't get it to compile. I have tried putting all sorts of things inside the argument space of the call and it still won't compile.
I just want the first execution to be NOW rather than after a minute which is the default behaviour.
Yay!! As a part of putting together these cut-down sketches for the forum, I thought to try dropping the brackets from after the new call and this compiled.
Clearly what (void *) in the definition means (at least in part) is that you can call it without brackets in the call statement. If only I could find a document that told me that.
PaulRB January 12, 2022, 8:40am 4I have tried putting all sorts of things inside the argument space of the call and it still won't compile.
Such as what? The parameter needs to be something with type void*. That means a pointer to... something/anything.
killzone_kid January 12, 2022, 8:40am 5you can send nullptr in this case
ReadCT(nullptr);
PaulRB January 12, 2022, 8:44am 6Clearly what (void *) in the definition means (at least in part) is that you can call it without brackets in the call statement.
No. If you leave off the brackets, the function does not get called.
bolJunk = ReadCT;simply assigns, to the variable boljunk, a pointer to the function ReadCT. Since booljunk is a Boolean, it can't hold the function pointer and probably always gets set to true I suspect.
westfw January 12, 2022, 8:59am 7bool ReadCT(void *)
"void *" means "a pointer to "something not tightly specified." A sort of hole in C's "strong typing."
It's frequently used for "callbacks" from service routines, in the sense that if you have a low-level timer alarm function, you can register a function for the low level call, without the low-level call needing to know the details of how the higher level code works. The pointer CAN be to a struct containing a large amount of data.
In your example, it might look like:
void setup() { // call ReadCT every 60s with a pointer to Serial as it's argument OutputTimer.every(60000, ReadCT, (void *)&Serial); } bool ReadCT(void *arg) { Stream *output = (Stream *)arg; // our argument was an output stream. Make it so. output->print("Entered ReadCT"); // output message to the defined stream. }If the ReadCT() that you've defined doesn't need any arguments, then you can just pass null, or nulptr, or 0, or whatever. But if it's expecting a particular pointer, you had better provide that type of pointer! eg:
ReadCT((void *)&Serial3);(In C, the casts to (void *) would not be necessary. I think (but am not sure) that C++ is fussier.)
J-M-L January 12, 2022, 9:17am 8It’s a generic pointer
See https://www.learncpp.com/cpp-tutorial/void-pointers/
As they say
C++ actually offers a much better way to do the same thing (via function overloading) that retains type checking to help prevent misuse. Many other places where void pointers would once be used to handle multiple data types are now better done using templates, which also offer strong type checking.
So if you can avoid this, it is better to do so but if this is what you need to deal with then…
gcjr January 12, 2022, 11:33am 9i've often used void * as the argument type to function ptrs in tables to allow a generic typedef to be used for multiple purpose. those functions would cast the arg as needed
the advantage of passing an argument as a ptr is that is usually the largest size variable possible and void suggests this purpose (i.e. slang)
a trivial example
// // example state machine // #include <stdio.h> #include "stateMach.h" // ------------------------------------------------ Status a (void* a) { printf ("%s:\n", __func__); return OK; } // ------------------------------------------------ Status b (void* a) { printf ("%s:\n", __func__); return OK; } // ------------------------------------------------ Status c (void* a) { printf ("%s:\n", __func__); return OK; } // ------------------------------------------------ Status __ (void* a) { printf ("%s:\n", __func__); return OK; } // -------------------------------------------------------------------- #define N_STATE 3 #define N_STIM 2 typedef enum { S0, S1, S2 } State_t; typedef Status(*Action_t)(void*) ; State_t smTransitionTbl [N_STATE] [N_STIM] = { { S1, S2, }, { S0, S2, }, { S2, S1, }, }; Action_t smActionTbl [N_STATE] [N_STIM] = { { a, b }, { c, __ }, { __, a }, }; // ------------------------------------------------ char *msg1 [] = { "State machine has 3 states and 2 stimuli.", "It has the following state transistion and action routine tables.", "A __() represents do nothing and is easily identified in table.", "Each row is indexed by a state and each column a stimulus.", "Of course, meaningful action routine names are helpful.", }; char *msg2 [] = { "Enter valid stimuli [0-1]:" }; void smHelp (void) { for (int i = 0; i < sizeof(msg1)/sizeof(char*); i++) printf (" %s\n", msg1 [i]); for (int state = 0; state < N_STATE; state++) { printf ("%8s", ""); for (int stim = 0; stim < N_STIM; stim++) printf (" %d", smTransitionTbl [state][stim]); printf ("%8s", ""); for (int stim = 0; stim < N_STIM; stim++) { if (a == smActionTbl [state][stim]) printf (" a()"); else if (b == smActionTbl [state][stim]) printf (" b()"); else if (c == smActionTbl [state][stim]) printf (" c()"); else printf (" __()"); } printf ("\n"); } for (int i = 0; i < sizeof(msg2)/sizeof(char*); i++) printf (" %s\n", msg2 [i]); } // ------------------------------------------------ static State_t _smState = S0; Status smEngine (Stim_t stim) { Action_t func; State_t last = _smState; if (N_STIM <= stim) return ERROR; func = smActionTbl [_smState] [stim]; _smState = smTransitionTbl [_smState] [stim]; printf (" stim %d, transition from state %d to %d, exec ", stim, last, _smState); return (*func) (NULL); } J-M-L January 12, 2022, 11:42am 10@gcjr interesting example.
for (int i = 0; i < sizeof(msg1)/sizeof(char*); i++) printf (" %s\n", msg1 [i]);
you could use a string literal to make your life easier!
// see https://en.cppreference.com/w/cpp/language/string_literal const char* s1 = R"___( State machine has 3 states and 2 stimuli. It has the following state transistion and action routine tables. A __() represents do nothing and is easily identified in table. Each row is indexed by a state and each column a stimulus. Of course, meaningful action routine names are helpful. )___"; void setup() { Serial.begin(115200); Serial.println(); Serial.println(s1); } void loop() {}the IDE does not recognise that too well, so auto-indent is fucked up afterwards thus it's best defined in a separate .h and imported into the main code
gcjr January 12, 2022, 12:23pm 11that code must be 20 years old.
J-M-L January 12, 2022, 12:47pm 12this explains why ![]()
string literal appeared formally in August 2011 (C++11) if I remember correctly
system Closed July 11, 2022, 12:47pm 13This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
Related topics
| Topic | Replies | Views | Activity |
|---|---|---|---|
| Diferencias entre Funcion() y Funcion(void *) Español | 3 | 68 | February 21, 2026 |
| Void STOP (void) - Bedeutung Deutsch | 13 | 161 | September 24, 2025 |
| Used Void and then did not use Void? I don't understand why? Programming | 5 | 135 | May 29, 2025 |
| New Il tempo delle librerie è finito.... Software | 18 | 1240 | May 7, 2021 |
| How can i add new [voids] functions to my code? Programming | 27 | 547 | January 29, 2026 |
Tag » What Does Void Mean In Arduino
-
Void - Arduino Reference
-
Tutorials? And What Does The 'void' Function Mean? - Arduino Forum
-
Using "Void" - Programming Questions - Arduino Forum
-
Setup(void)? Why? - Programming Questions - Arduino Forum
-
What Does "void (*)()" Mean - Pass Functions As Argument
-
Arduino Void Setup And Void Loop Functions [Explained]
-
Arduino Functions - Robolink Basecamp
-
Syntax | Let's Start Coding | Coding For Kids
-
Arduino Tutorial 3: What Are Void Setup() And Void Loop() In Arduino
-
Creating Void Functions - YouTube
-
Void Ne Demek Arduino?
-
Digital Sandbox Arduino Companion - Learn.
-
What Is The Difference Between A Void Setup And A Void Loop? - Quora
-
What Is Void Setup And Void Loop?