Inline funtions question

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!

I'm working in a new project using avr-gcc for a atmega128.
Since I want to make the code simple and modular, I have a c file for each part of the code that I can separate.
In order to maintain that modularity, I keep variables local to each c file, so that I don't end up with lots of global variables.

For example:

//main.c
#include "counter.h"

int main(void)
{
  ...
  SetCounter(10);
  ...
}

//counter.c
#include "counter.h"

uint8_t counter_value;

void SetCounter(uint8_t value)
{
  counter_value = value;
}

//counter.h
void SetCounter(uint8_t value);

However, the SetCounter() function is simple enough to become inline.

Now it comes the question:

Q: How should I make the function inline?

A1: move the code from counter.c to main.c and use "static inline"
It's not what I wanted since the code would become a mess in just one file: main.c

A2: Define counter.c functions in the header (counter.h)? Use "extern inline" or just "inline"? Should the variables be also moved to the header?

A3: include counter.c in main.c instead of its header and don't compile counter.c into counter.o?

A4: A better solution posted by you?

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A4:
In counter.h:

inline void SetCounter(uint8_t value) __attribute__((always_inline));
static void SetCounter(uint8_t value) {
  counter_value = value;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Inlines are usually placed in header files. Although not technically wrong, including .c files into other .c files isn't normally done. Doing so would mean you could only include it once or that the included .c file would need to be written like a header file (with declarations and file scope definitions only).

Also, remember that according the C99 language the inline keyword is only a hint to the compiler . Each compiler has its own way to help you force something to always be inlined. For GCC it looks like this:

static __inline__ void function(void) __attribute__((always_inline));

More reading:
http://www.greenend.org.uk/rjk/2...

-Brad

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks!

So, I assume the best thing to do is to change the code to:

//main.c
#include "counter.h"

int main(void)
{
  ...
  SetCounter(10);
  ...
}

//counter.c
#include "counter.h"

uint8_t counter_value;

//counter.h
extern uint8_t counter_value;

extern inline void SetCounter(uint8_t value)
{
  counter_value = value;
}

But this way I would have the variable counter_value available everywhere, which was not my intention...

On the other hand I understand that in order to inline a function into another translation unit, the compiler must have access to the variable address when compiling the function calling translation unit, so it can generate code for it...

Am I right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What you probably want is C++ classes... You can have them
if you want. It's just a different approach than C then.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure of what I want yet.

I'm just trying to figure out the best efficient(in code size and speed) and tidy(easy to read) code technique.

How would you program the initial situation, taking into account that the code would be long?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

logic_bit wrote:
I'm just trying to figure out the best efficient(in code size and speed) and tidy(easy to read) code technique.
Those two goals often do not coincide.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dl8dtl wrote:
What you probably want is C++ classes... You can have them
if you want. It's just a different approach than C then.
namespaces are closer yet.
He could use C++ as C+namespaces and get what he probably wants.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!

After reading a few about inlining, I decided to use the following strategy (I'm not sure if it's good or not):

-if the function is really simple and small I use

// header file
extern inline void SetCounter(uint8_t value)
{
  ...
}

-if the function is complex, big and called a few times:

// c file
void SetCounter(uint8_t value)
{
  ...
}

-if the function is not too big and is only called once:

// header file
static inline void SetCounter(uint8_t value)
{
  ...
}

so the compiler can decide to inline or not in case that later I'd call the function in more places.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How can you have a function that is both static in one place and extern in another?

Also { and } in the context of a function should never appear in a header file. You put declarations, not definitions in header files - that is the {...} is replaced with a ;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Also { and } in the context of a function should never appear in a header file.

Well, "static inline" functions are an exception to this rule. It's the only
way the compiler can inline them within all translation units, yet you don't
have to maintain multiple copies of the same source code. Technically, they
form one instance of the underlying "static" functions per translation unit
where they are used.

"extern inline" is something very GCC specific, I'd normally avoid it.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
How can you have a function that is both static in one place and extern in another?
For clarity, he should probably used a metasyntactic
word such as foo, bar or fred instead of SetCounter.
In any case, one can have a static function named qux
in one file and an external function named qux in another.
It just isn''t a good idea.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
clawson wrote:
How can you have a function that is both static in one place and extern in another?
For clarity, he should probably used a metasyntactic
word such as foo, bar or fred instead of SetCounter.
In any case, one can have a static function named qux
in one file and an external function named qux in another.
It just isn''t a good idea.

You're right, I should have used different names for different situations.
dl8dtl wrote:
"extern inline" is something very GCC specific, I'd normally avoid it.

I used "extern inline" to ensure that stand-alone object code was never emitted. Does "inline" with "__attribute__((always_inline))" as suggested by "schickb" has the same effect?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

always_inline guarantees the function will be inlined, even if the
compiler's heuristic would suggest that not inlining it might get
better optimization.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.