Is function in struct efficient in c? - Page 1
Forum section: electronics / general

author: navidrct
author_rank: Regular Contributor
timestamp: November 08, 2017, 02:50:17 pm
content: HiI'm using keil for working with arm mcuIf I put all function that related to each other to a struct , my code will be so easy to readI do this and in dis assembly code I saw five line for thatBut when I use the exact function and I see the dis assembly I saw one lineI really like to use first method . Do u have any suggestion to work it efficiently?

author: stmdude
author_rank: Frequent Contributor
timestamp: November 08, 2017, 02:55:58 pm
content: A few lines of example code would go a long way to explain what you're talking about.Are you talking about function-pointers in a struct? Like:Code:struct {int (*my_function_pointer)(int a,int b);} somefunctions;?

author: navidrct
author_rank: Regular Contributor
timestamp: November 08, 2017, 03:03:14 pm
content: Quote from: stmdude on November 08, 2017, 02:55:58 pmSorry I'm in mobile and I did not have any sample codeYes that was what I'm talking about

author: Jeroen3
author_rank: Super Contributor
timestamp: November 08, 2017, 03:09:14 pm
content: QuoteYou can't do that in C without messing around. I wouldn't recommend it.You can use C++ with classes instead. It's designed to support this.Functionpointersare no problem, they're just like regular pointers.Remember structs are just a way to abstract data in memory. It is not necessarily faster, except allowing cleaner code.

author: navidrct
author_rank: Regular Contributor
timestamp: November 08, 2017, 03:24:53 pm
content: Quote from: Jeroen3 on November 08, 2017, 03:09:14 pmI don't know how to use c++ in keil at all.If I use function pointer in struct to categorize my functions it won't be efficient right?

author: stmdude
author_rank: Frequent Contributor
timestamp: November 08, 2017, 03:43:59 pm
content: Quote from: navidrct on November 08, 2017, 03:03:14 pmOk, that isn't a problem (performance wise) unless you're chasing every single cycle you can. It'll add one memory-read ("mov") to each call to the function, worst-case. I wouldn't worry about it at all.Edit: It'll disable some optimizations though. Routines called through function-pointers can't be inlined.

author: dmills
author_rank: Super Contributor
timestamp: November 08, 2017, 03:51:55 pm
content: Also, cache performance, IPO, and it makes every struct bigger (Not the case for C++ where non virtual functions can be resolved at compile time).I would use a C++ compiler (With RTTI and exceptions switched off) if I really wanted to do this routinely. The C++ compiler will know how to get clever with this stuff in a way that a C compiler just does not.There are places it makes sense, some bits of network stacks spring to mind where implementing state machines by changing function pointers withing structures is actually sort of reasonable.Regards, Dan.

author: navidrct
author_rank: Regular Contributor
timestamp: November 08, 2017, 04:00:16 pm
content: Quote from: dmills on November 08, 2017, 03:51:55 pmThanks allot that was awesome

author: hans
author_rank: Super Contributor
timestamp: November 08, 2017, 04:08:04 pm
content: Done coding with function pointers in C before. Can't recommended.You're basically re-implementing C++, but with none of the strong-typing compile checks and other benefits C++ brings over C. You will be chasing your own tail why some piece of code will fail to run because some function pointer is incorrectly set.Moreover I think classes in C++ will do a better job in terms of efficiency.Like stmdude said, function pointers in C will kill the optimizer and will prevent it from inlining functions. In my own projects I wrote C++ drivers for setting up and using GPIO's, bitbanging I2C, reading/writing EEPROM and a settings manager. With high optimizations GCC was able to inline that whole chain into the settings manager code. If you're doing function pointers in C it won't even come close.Watch out with virtual methods though. Those are not that efficient, perhaps a bit worse than function pointers in C. However the compiler will do the housekeeping for you, which is nice.I suppose you're researching now how to write your next project, and in that case you might as well invest in a C++ tool and learning how to use it.Or accept that C has a certain flavour to it: it's low-level, it's your responsibility to write good code. That is awesome. But writing organized large projects can feel like a chore.

author: andyturk
author_rank: Frequent Contributor
timestamp: November 08, 2017, 04:19:16 pm
content: Quote from: hans on November 08, 2017, 04:08:04 pmHow so?

author: dgtl
author_rank: Regular Contributor
timestamp: November 08, 2017, 04:33:33 pm
content: In case of using some function pointers where using enums with switches or other methods do not make sense, they are fine. Look at the Linux kernel source code, it is a huge c-only project and it uses quite a lot of function pointers. But just calling everything via function pointers leads to re-inventing the wheel (C++ vtable). Find a C++ compiler and use it.In case of microcontroller projects, my reasoning of using or not using some technology goes like this: do not do anything in runtime, that can be pre-calculated compile time. So in case your function pointer can only have a single value, it is pointless of using function pointers. Either just define the function header and expect some other compilation unit (c file) to implement it; use preprocessor defines in headers to allow mapping functions to exact implementations (like a lot of projects do "#define my_printf printf"), use weak functions (like interrupts in ARM world are usually done) etc etc. Keep in mind, that unlike for regular computer libraries, the scope of a project embedded world is usually limited at the compile time and usually there are no plugins or other methods to bring in new code. So there is no point of pushing code to uc that won't be used at all or that will be used only in a few pre-defined cases.Also another point is safety. Having function pointers in RAM is a risk due to stack overflow or buffer overflow problems (in case the struct with function pointers is not const). For a lot of embedded projects, the worst stack size is not throrughly investigated, it is just hopefully big enough. If things go bad, the function pointer corruption is usually fatal, other kinds of corruptions can be somewhat handled. See for example misra-c if more interested.

author: nctnico
author_rank: Super Contributor
timestamp: November 08, 2017, 04:36:52 pm
content: Quote from: hans on November 08, 2017, 04:08:04 pmI fully agree! Currently I'm working on an existing piece of code which uses function pointers and void pointers to data which should be 32 bit aligned -shudder-.

author: JPortici
author_rank: Super Contributor
timestamp: November 08, 2017, 06:36:40 pm
content: Quote from: Jeroen3 on November 08, 2017, 03:09:14 pmwhat do you mean exactly?I use structures a lot to pack data/properties/etc about a sensor for example, because then in my fuction i just use pointer to the structure. Only the base address is put on the stack and the compiler takes care of the addressing.I like how cleaner the code gets (As you point out) and i like the idea that i have a "contained" space where everything about my sensor or whatever is, if such a place can exist in CAlso, i may not have a C++ compiler available for my MCU of choice(or have i misinterpreted the OP's phrase?)

author: hans
author_rank: Super Contributor
timestamp: November 08, 2017, 06:42:27 pm
content: Quote from: andyturk on November 08, 2017, 04:19:16 pmBecause virtual methods are defined in some kind of abstract class, which is then implemented by other classes. E.g. if you have an abstract sensor class and have different temperature sensor implementations. From an object orientated programming point of view this is great.But it's run-time inheritance. Function pointers are stored in a vtable that is added to each type of class instantiated in the code. This is very similar to a struct of function pointers. At least the compilers does the chores for you, but it will generate more code in doing so to solve the inheritance at run-time. And so it will be slower in run-time.Fortunately you can still explore the extra freedom of C++ without virtual methods, so it's not a disaster. Moreover if you're dealing with high-level concepts of your system, those few extra instructions for e.g. 100 calls/second won't matter neither. But if you're using this on a very low level like MCU peripherals and call abstractions at a high-rate (as you do) then it will matter.In my experience GCC won't be able to optimize virtual method calls, even if the exact type of class is known at compile time and is not going to change. In that case you're better off [in terms of performance] using templates instead of virtual methods. However creating types composed of multiple template objects is not fun (and CRTP=brainfuck), so it's a trade-off what you want.Personally I write template classes for hardware abstractions. You can get negative cost C++ code (compared to C) from doing so like I mentioned. Then at a higher level in the firmware I will consider using virtual methods.

author: Jeroen3
author_rank: Super Contributor
timestamp: November 08, 2017, 07:10:07 pm
content: Quote from: JPortici on November 08, 2017, 06:36:40 pmYou can't put a function inside a struct with c. You can only put pointers to functions in structs.It will literally tell you:error: #168: a function type is not allowed hereUsing structs as "object" containers is a common thing indeed. But you'd have to call the functionfoo(struct *bar).A bit like object oriented, but not quite.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 08, 2017, 07:41:06 pm
content: Aside of being pointless, it is nothing wrong with it. This is, sort of, the beginning of object oriented approach. You may make it useful if you have polymorphic objects which exhibit different behaviour (that is every object has its own function). In this case you actually save tons of code which would decide which function to call.In terms of efficiency, you add one indirection, so every access to the function will take few more cycles, but this should be Ok with you if you use C (as opposed to Assembler).C++ objects will add one more level of indirection, your objects will not contain pointers to functions, but rather a single pointer to a table of functions. So it will be even less efficient in terms of speed. Although, static functions will not be in the table and will be called directly.

author: andyturk
author_rank: Frequent Contributor
timestamp: November 08, 2017, 08:23:13 pm
content: Quote from: hans on November 08, 2017, 06:42:27 pmI doubt this is the case. At least, if there is any performance hit to using C++ virtual methods compared to rolling your own structs-with-fn-pointers, the difference is going to be vanishingly small.FWIW, I'm a heavy user of C++ on microcontroller hardware (Cortex-M) using GCC. C++ adds one 32-bit pointer (vptr) to objects that have virtual methods. That pointer indirects to the actual vtable which lives in flash. A virtual method call first needs to load the vptr out of SRAM and then use it to load the method address out of flash. That's two memory loads.The straight C style posted above essentially puts the entire vtable into each instance. You can get to the address of the method with only one memory load, but at a cost of burning more SRAM. So sure, one memory load is faster than two, but if that difference really matters, you've got other problems to deal with.

author: hans
author_rank: Super Contributor
timestamp: November 08, 2017, 10:43:58 pm
content: If you view it that way, then C++ will scale better in large applications because of RAM usage.But if you're writing a tight piece of code in terms of execution speed or latency, then these things can matter. I still think the C implementation could be marginally faster, but it maybe won't be much. Nevertheless, there is cost that often needs to be paid by abstraction, and depending on what you do that could be too high either case (despite all the software quality & development benefits).But in most cases modern microcontrollers are more than capable to handle C++, even the ones with 4KB of RAM or less. I think that if one is contemplating implementing C structs & function pointers, IMO there must be a great counter argument for not choosing C++.

author: Jeroen3
author_rank: Super Contributor
timestamp: November 09, 2017, 06:33:51 am
content: Arduino is C++, Mbed is C++.When your application complexity can benefit from C++, you probably won't notice the slight performance penalty.With static allocation I think think it isn't very noticeable at all.

author: nctnico
author_rank: Super Contributor
timestamp: November 09, 2017, 11:12:33 am
content: Quote from: Jeroen3 on November 09, 2017, 06:33:51 amThat and if you use function pointers to link objects in C then C++ will be faster because it can sort all these links out and do optimisations in either speed or size.

author: ejeffrey
author_rank: Super Contributor
timestamp: November 10, 2017, 05:05:03 am
content: Quote from: andyturk on November 08, 2017, 08:23:13 pmThis is correct. C++ virtual methods will almost always be as fast or faster than doing the same thing with function pointers in C. Its doing the same thing, but the compiler can constrain the behavior a lot more, so it can do a better job of optimizing.For instance, C++ knows that an objects virtual member pointer can't change over the life of an object. Therefore, if you call a virtual method in a tight loop, the compiler may be able to store the jump address in a register. If you use explicit function pointers, the compiler can't prove that the function pointer doesn't change as a result of the call and needs to reload it ever iteration.Virtual method calls do have a slight overhead to static calls of course, especially if the static call can be inlined. However, if you need the functionality of a dispatch table, virtual functions in C++ will be as fast or faster than rolling your own.C++ also has the advantage that if the compiler can statically determine the object type, it will automatically convert the virtual calls to static calls. That can include inlining the method if possible.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 10, 2017, 02:23:21 pm
content: Quote from: ejeffrey on November 10, 2017, 05:05:03 amThis is incorrect. Calling virtual method requires fetching a pointer to the VMT, then the pointer has to be fetched from VMT and the function called. Calling a function through a pointer is definitely faster. Therefore virtual function call cannot be faster at any rate.As to the optimizations, typically C and C++ is the same compiler, and consequently will have the same optimizations. If you have a pointer which always point to the same function (and the compiler knows it), the compiler can eliminate it whether it is C or C++.

author: glarsson
author_rank: Frequent Contributor
timestamp: November 10, 2017, 05:53:11 pm
content: Quote from: NorthGuy on November 10, 2017, 02:23:21 pmThe compiler knows it if you declare the function pointer const.

author: westfw
author_rank: Super Contributor
timestamp: November 10, 2017, 11:12:11 pm
content: QuoteI still don't think I understand what the original poster is trying to do. Can you post actual code?On ARM, calling a global function means that the compiler will assemble a single "branch and link" instruction, while dereferencing a pointer to a function in a struct means getting the (possibly dynamic) location of a struct, loading the pointer from the struct, and doing an indirect branch on the result. Five instructions sounds about right.Based on the subsequent discussion, careful use of "const" and/or "static" might allow the C Compiler to optimize the structure pointer references...It really does sound like you're looking for C++ "object methods" - note that normal (not virtual) C++ object methods do NOT use pointers; they're based on compile-time magic.

author: gnif
author_rank: Unknown
timestamp: November 10, 2017, 11:32:27 pm
content: Function pointers are very useful if used properly, such as bypassing a ton of detection logic after/at first time initialization/use (ie, lazy/late initialization). A project I am currently working on uses them for pixel format handling routines, if the frame pixel format type suddenly changes, everything is reinitialized and the handler function pointer is changed to the one for the correct type avoiding complex conditionals every single frame of data.In the instance of using them everywhere, I agree with most people here, use C++, you're likely to cause yourself bugs that are near impossible to track down, such as forgetting to initialize one of the pointers, or memory corruption messing with the pointers making debugging the corruption very hard.For an atomic/singleton instance of an object the pattern I follow is this:Code:struct ExampleState{int x, y;};static struct ExampleState example;int example_initialize(){example.x = 0;example.y = 10;return 0;}void example_deinit(){// do stuff...}When multiple instances are needed (ie, like objects) I use the following pattern:Code:struct ExampleState{int x, y;};struct ExampleState * example_initialize(){// obviously for embedded you may not want to malloc like this.struct ExampleState * state = (struct ExampleState *)malloc(sizeof(struct ExampleState));state->x = 0;state->y = 10;return state;}void example_deinit(struct ExampleState * state){if (!state){fprintf(stderr, "warning: null pointer passed to " __FUNC__);return;}// do stufffree(state);}by prefixing all methods related to the module with the module name it makes your code clear and easy to follow without the need for function pointers everywhere. Really what is cleaner "example->initialize()" or "example_initialize()"? The only thing here that C++ would afford additional is protection (public/private/protected) and extra features such as templates, which for most projects are not needed. Inheritance also, but that can also be done in C without too much trouble with function pointers, the Linux kernel is a perfect example of this, pick any kernel driver to see how they initialize.Edit:Actually private protection can be done also by simply not declaring the functions in the header.

author: bd139
author_rank: Super Contributor
timestamp: November 11, 2017, 06:15:14 am
content: I think the only time I use a function pointer these days is whe I want to inject a custom allocator into a library I’ve written. I’ll have a function which takes malloc/free function pointer which overrides the default implementation if called.I’ll only use C if I’m writing a library that needs to be pulled in from other languages (python in particular) where it’s a shit ton easier using it with FFI systems.Anything greater calls for C++

author: Feynman
author_rank: Regular Contributor
timestamp: November 14, 2017, 08:37:13 pm
content: If something makes the code more readable and maintainable, i wouldn't care too much about a little loss in efficiency.Sometimes, function pointers are a neat tool, e. g. for implementing jump tables.

author: Howardlong
author_rank: Super Contributor
timestamp: November 14, 2017, 08:59:32 pm
content: I might’ve missed it in this thread, but particularly in embedded systems pointers to functions, as well as for callbacks, are reasonably common in state machines as an alternative to large case statements.Totally agred with the previous poster, it’s whatever makes the most sense in terms of readability, maintenance and efficiency.

author: nctnico
author_rank: Super Contributor
timestamp: November 15, 2017, 09:35:39 am
content: Quote from: Howardlong on November 14, 2017, 08:59:32 pmBut you have to be carefull though. I don't use function pointers if they aren't constant (=fixed in flash) otherwise memory corruption can screw up things badly. AFAIK MISRA doesn't allow to use function pointers at all (or at least ones that are not in RAM).

author: bd139
author_rank: Super Contributor
timestamp: November 15, 2017, 09:40:56 am
content: I tend to write state machines using macros that wrap a switch block and loop. No pointers, no mallocs. Making it safe and user-readable are the most important things.

author: Howardlong
author_rank: Super Contributor
timestamp: November 15, 2017, 12:00:51 pm
content: Quote from: nctnico on November 15, 2017, 09:35:39 amI was uhming and arhing whether to include "security" in my list of caveats but didn't want to muddy the waters.One case I have used mutable function pointers is in an interrupt driven software slave I2C on a very low end device, without either hardware I2C or vectored interrupts, in order to gain sufficiently fast response. It was faster than a bunch of nested if-then-else and case statements, and the difference between it working and not working in this case.It's just one of the key skills of engineering, compromising and balancing between different criteria and requirements. On the one I cited, it was a very price sensitive application, so much so the cost of a device with hardware I2C would have made it unviable!In general, the default position for an FSM these day is a case statement, but I don't think it's too much to ask any reasonably proficient C programmer to be able to deal with function pointers put in there for the right reasons.

author: dmills
author_rank: Super Contributor
timestamp: November 15, 2017, 12:59:04 pm
content: Indeed, sometimes you have to do these things (See also Duffs device) and other such cool and fast but overly complicated stuff.Hackmem is full of such things.Regards, Dan.

author: legacy
author_rank: Super Contributor
timestamp: November 15, 2017, 02:57:24 pm
content: in the softcore I am designing some special instructions have been created to simply struct of functions since they are very very very useful