#define vs. enums for addressing peripherals - c

I have to program peripheral registers in an ARM9-based microcontroller.
For instance, for the USART, I store the relevant memory addresses in an enum:
enum USART
{
US_BASE = (int) 0xFFFC4000,
US_BRGR = US_BASE + 0x16,
//...
};
Then, I use pointers in a function to initialize the registers:
void init_usart (void)
{
vuint* pBRGR = (vuint*) US_BRGR;
*pBRGR = 0x030C;
//...
}
But my teacher says I'd better use #defines, such as:
#define US_BASE (0xFFFC4000)
#define US_BRGR (US_BASE + 0x16)
#define pBRGR ((vuint*) US_BRGR)
void init_usart (void)
{
*pBRGR = 0x030C;
}
Like so, he says, you don't have the overhead of allocating pointers in the stack.
Personally, I don't like #defines much, nor other preprocessor directives.
So the question is, in this particular case, are #defines really worth using instead of enums and stack-allocated pointers?
Related question: Want to configure a particular peripheral register in ARM9 based chip

The approach I've always preferred is to first define a struct reflecting the peripherals register layout
typedef volatile unsigned int reg32; // or other appropriate 32-bit integer type
typedef struct USART
{
reg32 pad1;
reg32 pad2;
reg32 pad3;
reg32 pad4;
reg32 brgr;
// any other registers
} USART;
USART *p_usart0 = (USART * const) 0xFFFC4000;
Then in code I can just use
p_usart0->brgr = 0x030C;
This approach is much cleaner when you have multiple instances of the same sort of peripheral:
USART *p_usart1 = (USART * const) 0xFFFC5000;
USART *p_usart2 = (USART * const) 0xFFFC6000;
User sbass provided a link to an excellent column by Dan Saks that gives much more detail on this technique, and points out its advantages over other approaches.
If you're lucky enough to be using C++, then you can add methods for all the common operations on the peripheral and nicely encapsulate the devices peculiarities.

I am afraid that enum are a dead end for such a task. The standard defines enum constants to be of type int, so in general they are not compatible with pointers.
One day on an architecture with 32bit int and 64bit pointers you might have a constant that doesn't fit into an int. It is not well defined what will happen.
On the other hand the argument that enum would allocate something on the stack is not valid. They are compile time constants and have nothing to do with the function stack or no more than any constants that you specify through macros.

Dan Saks has written a number of columns on this for Embedded Systems Programming. Here's one of his latest ones. He discusses C, C++, enums, defines, structs, classes, etc. and why you might one over another. Definitely worth reading and always good advice.

In my experience, one big reason to use #define for this kind of thing is that it's more of the standard idiom used in the embedded community.
Using enums instead of #define will generate questions/comments from instructors (and in the future, colleagues), even when using other techniques might have other advantages (like not stomping on the global identifier namespace).
I personally like using enums for numeric constants, but sometimes you need to do what is customary for what and where you're working.
However, performance shouldn't be an issue.

The answer is always do whatever the teacher wants and pass the class then on your own question everything and find out if their reasons were valid and form your own opinions. You cant win against the school, not worth it.
In this case it is easy to compile to assembler or disassemble to see the difference if any between the enum and define.
I would recommend the define over enum, have had compiler discomfort with enums. I highly discourage using pointers the way you are using them, I have seen every compiler fail to accurately generate the desired instructions, it is rare but when it happens you will wonder how your last decades of coding ever worked. Pointing structs or anything else is considerably worse. I often get flamed for this, and expect to this time around. Too many miles around the block, fixed too much broken code with these problems to ignore the root cause.

I wouldn't necessarily say that either way is better. It is just personal preference. As for your professor's argument, it is really a moot point. Allocating variables on the stack is one instruction, no matter how many there are, usually in the form sub esp, 10h. So if you have one local or 20, it is still one instruction to allocate the space for all of them.
I would say that the one advantage of the #include is that if for some reason down the road you wanted to change how that pointer is accessed, you just need to change it in one location.

I would tend towards using an enum, for potential future compatibility with C++ code. I say this because at my job, we have a lot of C header files shared between projects, some of which use C code and some of which use C++. For those using C++, we'd often like to wrap the definitions in a namespace, to prevent symbol masking, but you can't assign a #define to a namespace.

Related

Best practice on writing constant parameters for embedded systems

This is a case of "static const” vs “#define” in C" for embedded systems.
On large/mid projects with "passed-down" code and modules, what is the best practice on writing constant parameters for your include files, modules, etc?
In a code "passed-down" where you don't know if the names you're choosing are defined in some other included file or might be called with extern or as macros in some other file that might include your file.
Having these 3 options:
static const int char_height = 12;
#define CHAR_HEIGHT 12
enum { char_height = 12 };
which one would be better (on an embedded system with unknown memory constraints)?
The original code uses mainly #define's for this, but these kind of constants are haphazardly implemented in several ways (and at different locations even in the same files) since it seems several people developed this demo software for a certain device.
Specifically, this is a demo code, showing off every hardware and SDK feature of a certain device.
Most of the data I'm thinking about is the kind used to configure the environment: screen dimensions, charset characteristics, something to improve the readability of the code. Not on the automatic configuration a compiler and pre-processor could do. But since there's a lot of code in there and I'm afraid of global name conflicts, I'm reluctant to use #define's
Currently, I'm considering that it would be better to rewrite the project from scratch and re-implement most of the already written functions to get their constants from just one c file or reorganize the constants' implementation to just one style.
But:
This is a one person project (so it would take a lot of time to re-implement everything)
The already implemented code works and it has been revised several times. (If it's not broken...)
Always consider readability and memory constraints. Also, macros are simply copy/paste operations that occur before compilation. With that being said I like to do the following:
I define all variables that are constant as being static const if they are to be used in one c file (e.g. not globally accessible across multiple files). Anything defined as const shall be placed in ROM when at file scope. Obviously you cannot change these variables after they're initialized.
I define all constant values using #define.
I use enumerations where it adds to readability. Any place where you have a fixed range of values I prefer enumerations to explicitly state the intent.
Try to approach the project with an object oriented perspective (even though c isn't OO). Hide private functions (don't create a prototype in the header), do not use globals if you can avoid it, mark variables that should only reside in one c module (file) as static, etc.
They are 3 different things that should be used in 3 different situations.
#define should be used for constants that need to be evaluated at compile time. One typical example is the size of a statically allocated array, i.e.
#define N 10
int x[N];
It is also fine to use #define all constants where it doesn't matter how or where the constant is allocated. People who claim that it is bad practice to do so only voice their own, personal, subjective opinions.
But of course, for such cases you can also use const variables. There is no important difference between #define and const, except for the following cases:
const should be used where it matters at what memory address a constant is allocated. It should also be used for variables that the programmer will likely change often. Because if you used const, you an easily move the variable to a memory segment in EEPROM or data flash (but if you do so, you need to declare it as volatile).
Another slight advantage of const is that you get stronger type safety than a #define. For the #define to get equal type safety, you have to add explicit type casts in the macro, which might get a bit harder to read.
And then of course, since consts (and enums) are variables, you can reduce their scope with the static keyword. This is good practice since such variables do not clutter down the global namespace. Although the true source of name conflicts in the global namespaces are in 99% of all cases caused by poor naming policies, or no naming policies at all. If you follow no coding standard, then that is the true source of the problem.
So generally it is fine to make constants global when needed, it is rather harmless practice as long as you have a sane naming policy (preferably all items belonging to one code module should share the same naming prefix). This shouldn't be confused with the practice of making regular variables global, which is always a very bad idea.
Enums should only be used when you have several constant values that are related to each other and you want to create a special type, such as:
typedef enum
{
OK,
ERROR_SOMETHING,
ERROR_SOMETHING_ELSE
} error_t;
One advantage of the enum is that you can use a classic trick to get the number of enumerated items as another compile-time constant "free of charge":
typedef enum
{
OK,
ERROR_SOMETHING,
ERROR_SOMETHING_ELSE,
ERRORS_N // the number of constants in this enum
} error_t;
But there are various pitfalls with enums, so they should always be used with caution.
The major disadvantage of enum is that it isn't type safe, nor is it "type sane". First of all, enumeration constants (like OK in the above example) are always of the type int, which is signed.
The enumerated type itself (error_t in my example) can however be of any type compatible with char or int, signed or unsigned. Take a guess, it is implementation-defined and non-portable. Therefore you should avoid enums, particularly as part of various data byte mappings or as part of arithmetic operations.
I agree with bblincoe...+1
I wonder if you understand what the differences are in that syntax and how it can/might affect implementation. Some folks may not care about implementation but if you are moving into embedded perhaps you should.
When bblincoe mentions ROM instead of RAM.
static const int char_height = 12;
That should, ideally, consume .text real estate and pre-init that real estate with the value you specified. Being const you wont change it but it does have a placeholder? now why would you need a placeholder for a constant? think about that, certainly you could hack the binary down the road for some reason to turn something on or off or change a board specific tuning parameter...
Without a volatile though that doesnt mean that compiler has to always use that .text location, it can optimize and put that value in as instructions directly or even worse optimize math operations and remove some math.
The define and enum do not consume storage, they are constants that the compiler chooses how to implement, ultimately those bits if they are not optimized away, land somewhere in .text sometimes everywhere in .text, depends on the instruction set how its immediates work the specific constant, etc.
So define vs enum is basically do you want to pick all the values or do you want the compiler to pick some values for you, define if you want to control it enum if you want the compiler to choose the values.
So it really isnt a best practice thing at all it is a case of determining what your program needs to do and choosing the appropriate programming solution for that situation.
Depending on the compiler and the target processor, choosing volatile static const int vs not doing that can affect the rom consumption. But it is a very specific optimization, and not a general answer (and has nothing to do with embedded but with compiling in general).
Dan Saks explains why he prefers the enumeration constant in these articles, Symbolic Constants and Enumeration Constants vs Constant Objects. In summary, avoid macros because they don't observe the usual scope rules and the symbolic names are typically not preserved for symbolic debuggers. And prefer enumeration constants because they are not susceptible to a performance penalty that may affect constant objects. There is a lot more details in the linked articles.
Another thing to considerer is performance. A #define constant can usually be accessed faster than a const variable (for integers) since the const will need to be fetched from ROM (or RAM) and the #define value will usually be an immediate instruction argument so it is fetched along with the instruction (no extra cycles).
As for naming conflicts, I like to use prefixes like MOD_OPT_ where MOD is the module name OPT means that the define is a compile-time option, etc. Also only include the #defines in your header files if they're part of the public API, otherwise use an .inc file if they're needed in multiple source files or define them in the source file itself if they're only specific to that file.

How to give readable names to elements of an array in C?

I'm inexperienced with C, and working on a microcontroller with messages stored in arrays where each byte does something different. How do I give each element of the array a human-readable name instead of referencing them as msg[1], msg[2], etc.?
Is this what structs are for? But "you cannot make assumptions about the binary layout of a structure, as it may have padding between fields."
Should I just use macros like this? (I know "macros are bad", but the code is already full of them)
#define MSG_ID msg[0]
#define MSG_COMMAND msg[1]
Oh! Or I guess I could just do
MSG_ID = 0;
MSG_COMMAND = 1;
MSG[MSG_ID];
That's probably better, if a little uglier.
If you want to go that route, use a macro, for sure, but make them better than what you suggest:
#define MSG_ID(x) (x)[0]
#define MSG_COMMAND(x) (x)[1]
Which will allow the code to name the arrays in ways that make sense, instead of ways that work with the macro.
Otherwise, you can define constants for the indexes instead (sorry I could not come up with better names for them...):
#define IDX_MSG_ID 0
#define IDX_MSG_COMMAND 1
And macros are not bad if they are used responsibly. This kind of "simple aliasing" is one of the cases where macros help making the code easier to read and understand, provided the macros are named appropriately and well documented.
Edit: per #Lundin's comments, the best way to improve readability and safety of the code is to introduce a type and a set of functions, like so (assuming you store in char and a message is MESSAGE_SIZE long):
typedef char MESSAGE[MESSAGE_SIZE];
char get_message_id(MESSAGE msg) { return msg[0]; }
char get_message_command(MESSAGE msg) { return msg[1]; }
This method, though it brings some level of type safety and allows you to abstract the storage away from the use, also introduces call overhead, which in microcontroller world might be problematic. The compiler may alleviate some of this through inlining the functions (which you could incentize by adding the inline keyword to the definitions).
The most natural concept for naming a set of integers in C are enumerations:
enum msg_pos { msg_id, msg_command, };
By default they start counting at 0 and increment by one. You would then access a field by msg[msg_id] for example.
It's fine to use a struct if you take the time to figure out how your compiler lays them out, and structs can very useful in embedded programming. It will always lay out the members in order, but there may be padding if you are not on an 8-bit micro. GCC has a "packed" attribute you can apply to the struct to prohibit padding, and some other compilers have a similar feature.

Managing without Objects in C - And, why can I declare variables anywhere in a function in C?

everyone. I actually have two questions, somewhat related.
Question #1: Why is gcc letting me declare variables after action statements? I thought the C89 standard did not allow this. (GCC Version: 4.4.3) It even happens when I explicitly use --std=c89 on the compile line. I know that most compilers implement things that are non-standard, i.e. C compilers allowing // comments, when the standard does not specify that. I'd like to learn just the standard, so that if I ever need to use just the standard, I don't snag on things like this.
Question #2: How do you cope without objects in C? I program as a hobby, and I have not yet used a language that does not have Objects (a.k.a. OO concepts?) -- I already know some C++, and I'd like to learn how to use C on it's own. Supposedly, one way is to make a POD struct and make functions similar to StructName_constructor(), StructName_doSomething(), etc. and pass the struct instance to each function - is this the 'proper' way, or am I totally off?
EDIT: Due to some minor confusion, I am defining what my second question is more clearly: I am not asking How do I use Objects in C? I am asking How do you manage without objects in C?, a.k.a. how do you accomplish things without objects, where you'd normally use objects?
In advance, thanks a lot. I've never used a language without OOP! :)
EDIT: As per request, here is an example of the variable declaration issue:
/* includes, or whatever */
int main(int argc, char *argv[]) {
int myInt = 5;
printf("myInt is %d\n", myInt);
int test = 4; /* This does not result in a compile error */
printf("Test is %d\n", test);
return 0;
}
c89 doesn't allow this, but c99 does. Although it's taken a long time to catch on, some compilers (including gcc) are finally starting to implement c99 features.
IMO, if you want to use OOP, you should probably stick to C++ or try out Objective C. Trying to reinvent OOP built on top of C again just doesn't make much sense.
If you insist on doing it anyway, yes, you can pass a pointer to a struct as an imitation of this -- but it's still not a good idea.
It does often make sense to pass (pointers to) structs around when you need to operate on a data structure. I would not, however, advise working very hard at grouping functions together and having them all take a pointer to a struct as their first parameter, just because that's how other languages happen to implement things.
If you happen to have a number of functions that all operate on/with a particular struct, and it really makes sense for them to all receive a pointer to that struct as their first parameter, that's great -- but don't feel obliged to force it just because C++ happens to do things that way.
Edit: As far as how you manage without objects: well, at least when I'm writing C, I tend to operate on individual characters more often. For what it's worth, in C++ I typically end up with a few relatively long lines of code; in C, I tend toward a lot of short lines instead.
There is more separation between the code and data, but to some extent they're still coupled anyway -- a binary tree (for example) still needs code to insert nodes, delete nodes, walk the tree, etc. Likewise, the code for those operations needs to know about the layout of the structure, and the names given to the pointers and such.
Personally, I tend more toward using a common naming convention in my C code, so (for a few examples) the pointers to subtrees in a binary tree are always just named left and right. If I use a linked list (rare) the pointer to the next node is always named next (and if it's doubly-linked, the other is prev). This helps a lot with being able to write code without having to spend a lot of time looking up a structure definition to figure out what name I used for something this time.
#Question #1: I don't know why there is no error, but you are right, variables have to be declared at the beginning of a block. Good thing is you can declare blocks anywhere you like :). E.g:
{
int some_local_var;
}
#Question #2: actually programming C without inheritance is sometimes quite annoying. but there are possibilities to have OOP to some degree. For example, look at the GTK source code and you will find some examples.
You are right, functions like the ones you have shown are common, but the constructor is commonly devided into an allocation function and an initialization function. E.G:
someStruct* someStruct_alloc() { return (someStruct*)malloc(sizeof(someStruct)); }
void someStruct_init(someStruct* this, int arg1, arg2) {...}
In some libraries, I have even seen some sort of polymorphism, where function pointers are stored within the struct (which have to be set in the initializing function, of course). This results in a C++ like API:
someStruct* str = someStruct_alloc();
someStruct_init(str);
str->someFunc(10, 20, 30);
Regarding OOP in C, have you looked at some of the topics on SO? For instance, Can you write object oriented code in C?.
I can't put my finger on an example, but I think they enforce an OO like discipline in Linux kernel programming as well.
In terms of learning how C works, as opposed to OO in C++, you might find it easier to take a short course in some other language that doesn't have an OO derivative -- say, Modula-2 (one of my favorites) or even BASIC (if you can still find a real BASIC implementation -- last time I wrote BASIC code it was with the QBASIC that came with DOS 5.0, later compiled in full Quick BASIC).
The methods you use to get things done in Modula-2 or Pascal (barring the strong typing, which protects against certain types of errors but makes it more complicated to do certain things) are exactly those used in non-OO C, and working in a language with different syntax might (probably will, IMO) make it easier to learn the concepts without your "programming reflexes" kicking in and trying to do OO operations in a nearly-familiar language.

Is using enums safe in all compilers?

In a discussion, a colleague told me that he never uses enum because he experienced that some C-compilers don't cope with the enum statement correctly.
He couldn't remember which compiler exactly had problems but among the problems, there were errors when doing something like
enum my_enum{
my_enum_first = 5;
my_enum_second = 10;
};
i.e. initializing enum values instead of letting the compiler do the automatic assignment. Another one was that the compiler decides for itself how big the enum is and therefore you could have unpredictable behavior for sizeof my_enum when compiling your code under various platforms.
To get around that, he told me to better use #defines to define the constant elements. But especially for using doxygen it's quite handy to have an enum (e.g. as function parameter) because in the generated documentation, you could simply click on my_enum and directly jump to the description of my_enum.
Another example would be code completion, where your IDE tells you what you could specify as valid parameters for functions. I know that – as long as you're compiling the code as C-code – that there's no type-safety (i.e. I could also specify 5 instead of my_enum_first), so the use of an enum seems to be a more cosmetic thing.
The question is: do you know any compilers that have limitations regarding the usage of enum?
Edit 1:
Regarding the environment: we are developing for various embedded platforms, so there could also be a compiler for some obscure micro-controller...
Edit 2:
He could tell me that the KEIL C51 compiler didn't play well with enums. Are there any experiences with current versions of the C51 compiler?
Compilers are free to choose the size of an enum based on its range of possible values. This only really becomes an issue if you're exposing enums in your API, and users of your code may be using a different compiler or build options.
In this case, confusion can be caused by the calling code passing in a 16-bit value, for example, and the receiving code expecting it to be 32 bits. If the top 16 bits of the passed-in value are left uninitialized, then bad things will happen.
You can work around this kind of issue by including a dummy entry in your enum to enforce a minimum size.
For example:
typedef enum {
FirstValue = 12,
SecondValue = 25,
DummyValue = 65536 // force enum to be greater than 16 bits
} MyEnum;
I'm pretty sure that a compiler that doesn't play nice with enum is an invalid compiler - enum is specified in the standard, so a failure to implement it means the compiler shouldn't technically be used to compile C (For the record, the scope of enumeration types is discussed in 6.2.1 and defined as a type in 6.2.5 (of C99), so one would assume that it's a valid part of the standard from thereon in)!
So no, I don't know of any such compilers.

Are nested functions a bad thing in gcc ? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I know that nested functions are not part of the standard C, but since they're present in gcc (and the fact that gcc is the only compiler i care about), i tend to use them quite often.
Is this a bad thing ? If so, could you show me some nasty examples ?
What's the status of nested functions in gcc ? Are they going to be removed ?
Nested functions really don't do anything that you can't do with non-nested ones (which is why neither C nor C++ provide them). You say you are not interested in other compilers - well this may be atrue at this moment, but who knows what the future will bring? I would avoid them, along with all other GCC "enhancements".
A small story to illustrate this - I used to work for a UK Polytechinc which mostly used DEC boxes - specifically a DEC-10 and some VAXen. All the engineering faculty used the many DEC extensions to FORTRAN in their code - they were certain that we would remain a DEC shop forever. And then we replaced the DEC-10 with an IBM mainframe, the FORTRAN compiler of which didn't support any of the extensions. There was much wailing and gnashing of teeth on that day, I can tell you. My own FORTRAN code (an 8080 simulator) ported over to the IBM in a couple of hours (almost all taken up with learning how to drive the IBM compiler), because I had written it in bog-standard FORTRAN-77.
There are times nested functions can be useful, particularly with algorithms that shuffle around lots of variables. Something like a written-out 4-way merge sort could need to keep a lot of local variables, and have a number of pieces of repeated code which use many of them. Calling those bits of repeated code as an outside helper routine would require passing a large number of parameters and/or having the helper routine access them through another level of pointer indirection.
Under such circumstances, I could imagine that nested routines might allow for more efficient program execution than other means of writing the code, at least if the compiler optimizes for the situation where there any recursion that exists is done via re-calling the outermost function; inline functions, space permitting, might be better on non-cached CPUs, but the more compact code offered by having separate routines might be helpful. If inner functions cannot call themselves or each other recursively, they can share a stack frame with the outer function and would thus be able to access its variables without the time penalty of an extra pointer dereference.
All that being said, I would avoid using any compiler-specific features except in circumstances where the immediate benefit outweighs any future cost that might result from having to rewrite the code some other way.
Like most programming techniques, nested functions should be used when and only when they are appropriate.
You aren't forced to use this aspect, but if you want, nested functions reduce the need to pass parameters by directly accessing their containing function's local variables. That's convenient. Careful use of "invisible" parameters can improve readability. Careless use can make code much more opaque.
Avoiding some or all parameters makes it harder to reuse a nested function elsewhere because any new containing function would have to declare those same variables. Reuse is usually good, but many functions will never be reused so it often doesn't matter.
Since a variable's type is inherited along with its name, reusing nested functions can give you inexpensive polymorphism, like a limited and primitive version of templates.
Using nested functions also introduces the danger of bugs if a function unintentionally accesses or changes one of its container's variables. Imagine a for loop containing a call to a nested function containing a for loop using the same index without a local declaration. If I were designing a language, I would include nested functions but require an "inherit x" or "inherit const x" declaration to make it more obvious what's happening and to avoid unintended inheritance and modification.
There are several other uses, but maybe the most important thing nested functions do is allow internal helper functions that are not visible externally, an extension to C's and C++'s static not extern functions or to C++'s private not public functions. Having two levels of encapsulation is better than one. It also allows local overloading of function names, so you don't need long names describing what type each one works on.
There are internal complications when a containing function stores a pointer to a contained function, and when multiple levels of nesting are allowed, but compiler writers have been dealing with those issues for over half a century. There are no technical issues making it harder to add to C++ than to C, but the benefits are less.
Portability is important, but gcc is available in many environments, and at least one other family of compilers supports nested functions - IBM's xlc available on AIX, Linux on PowerPC, Linux on BlueGene, Linux on Cell, and z/OS. See
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fnested_functions.htm
Nested functions are available in some new (eg, Python) and many more traditional languages, including Ada, Pascal, Fortran, PL/I, PL/IX, Algol and COBOL. C++ even has two restricted versions - methods in a local class can access its containing function's static (but not auto) variables, and methods in any class can access static class data members and methods. The upcoming C++ standard has lamda functions, which are really anonymous nested functions. So the programming world has lots of experience pro and con with them.
Nested functions are useful but take care. Always use any features and tools where they help, not where they hurt.
As you said, they are a bad thing in the sense that they are not part of the C standard, and as such are not implemented by many (any?) other C compilers.
Also keep in mind that g++ does not implement nested functions, so you will need to remove them if you ever need to take some of that code and dump it into a C++ program.
Nested functions can be bad, because under specific conditions the NX (no-execute) security bit will be disabled. Those conditions are:
GCC and nested functions are used
a pointer to the nested function is used
the nested function accesses variables from the parent function
the architecture offers NX (no-execute) bit protection, for instance 64-bit linux.
When the above conditions are met, GCC will create a trampoline https://gcc.gnu.org/onlinedocs/gccint/Trampolines.html. To support trampolines, the stack will be marked executable. see: https://www.win.tue.nl/~aeb/linux/hh/protection.html
Disabling the NX security bit creates several security issues, with the notable one being buffer overrun protection is disabled. Specifically, if an attacker placed some code on the stack (say as part of a user settable image, array or string), and a buffer overrun occurred, then the attackers code could be executed.
update
I'm voting to delete my own post because it's incorrect. Specifically, the compiler must insert a trampoline function to take advantage of the nested functions, so any savings in stack space are lost.
If some compiler guru wants to correct me, please do so!
original answer:
Late to the party, but I disagree with the accepted answer's assertion that
Nested functions really don't do anything that you can't do with
non-nested ones.
Specifically:
TL;DR: Nested Functions Can Reduce Stack Usage in Embedded Environments
Nested functions give you access to lexically scoped variables as "local" variables without needing to push them onto the call stack. This can be really useful when working on a system with limited resource, e.g. embedded systems. Consider this contrived example:
void do_something(my_obj *obj) {
double times2() {
return obj->value * 2.0;
}
double times4() {
return times2() * times2();
}
...
}
Note that once you're inside do_something(), because of nested functions, the calls to times2() and times4() don't need to push any parameters onto the stack, just return addresses (and smart compilers even optimize them out when possible).
Imagine if there was a lot of state that the internal functions needed to access. Without nested functions, all that state would have to be passed on the stack to each of the functions. Nested functions let you access the state like local variables.
I agree with Stefan's example, and the only time I used nested functions (and then I am declaring them inline) is in a similar occasion.
I would also suggest that you should rarely use nested inline functions rarely, and the few times you use them you should have (in your mind and in some comment) a strategy to get rid of them (perhaps even implement it with conditional #ifdef __GCC__ compilation).
But GCC being a free (like in speech) compiler, it makes some difference... And some GCC extensions tend to become de facto standards and are implemented by other compilers.
Another GCC extension I think is very useful is the computed goto, i.e. label as values. When coding automatons or bytecode interpreters it is very handy.
Nested functions can be used to make a program easier to read and understand, by cutting down on the amount of explicit parameter passing without introducing lots of global state.
On the other hand, they're not portable to other compilers. (Note compilers, not devices. There aren't many places where gcc doesn't run).
So if you see a place where you can make your program clearer by using a nested function, you have to ask yourself 'Am I optimising for portability or readability'.
I'm just exploring a bit different kind of use of nested functions. As an approach for 'lazy evaluation' in C.
Imagine such code:
void vars()
{
bool b0 = code0; // do something expensive or to ugly to put into if statement
bool b1 = code1;
if (b0) do_something0();
else if (b1) do_something1();
}
versus
void funcs()
{
bool b0() { return code0; }
bool b1() { return code1; }
if (b0()) do_something0();
else if (b1()) do_something1();
}
This way you get clarity (well, it might be a little confusing when you see such code for the first time) while code is still executed when and only if needed.
At the same time it's pretty simple to convert it back to original version.
One problem arises here if same 'value' is used multiple times. GCC was able to optimize to single 'call' when all the values are known at compile time, but I guess that wouldn't work for non trivial function calls or so. In this case 'caching' could be used, but this adds to non readability.
I need nested functions to allow me to use utility code outside an object.
I have objects which look after various hardware devices. They are structures which are passed by pointer as parameters to member functions, rather as happens automagically in c++.
So I might have
static int ThisDeviceTestBram( ThisDeviceType *pdev )
{
int read( int addr ) { return( ThisDevice->read( pdev, addr ); }
void write( int addr, int data ) ( ThisDevice->write( pdev, addr, data ); }
GenericTestBram( read, write, pdev->BramSize( pdev ) );
}
GenericTestBram doesn't and cannot know about ThisDevice, which has multiple instantiations. But all it needs is a means of reading and writing, and a size. ThisDevice->read( ... ) and ThisDevice->Write( ... ) need the pointer to a ThisDeviceType to obtain info about how to read and write the block memory (Bram) of this particular instantiation. The pointer, pdev, cannot have global scobe, since multiple instantiations exist, and these might run concurrently. Since access occurs across an FPGA interface, it is not a simple question of passing an address, and varies from device to device.
The GenericTestBram code is a utility function:
int GenericTestBram( int ( * read )( int addr ), void ( * write )( int addr, int data ), int size )
{
// Do the test
}
The test code, therefore, need be written only once and need not be aware of the details of the structure of the calling device.
Even wih GCC, however, you cannot do this. The problem is the out of scope pointer, the very problem needed to be solved. The only way I know of to make f(x, ... ) implicitly aware of its parent is to pass a parameter with a value out of range:
static int f( int x )
{
static ThisType *p = NULL;
if ( x < 0 ) {
p = ( ThisType* -x );
}
else
{
return( p->field );
}
}
return( whatever );
Function f can be initialised by something which has the pointer, then be called from anywhere. Not ideal though.
Nested functions are a MUST-HAVE in any serious programming language.
Without them, the actual sense of functions isn't usable.
It's called lexical scoping.

Resources