What's the difference between static inline void and void?
Asked Answered
S

6

17

I'm working in the C language and modifying code previously written by someone else. I'm struggling with a few things and I'm trying to understand as much as I can about what is going on as I can. So, as my question stated, what is the difference between static inline void and void when creating a function? I apologize in advance for the long post, but I wanted you to know I did do some research, but don't understand what I've found.

I found an explanation of static that confuses me:

The static specifier signifies that the function cannot be referenced from other files; that is, the name is not exported by the linker.

By reading this, I'm assuming referencing a function is different than calling a function? I assume that because this function is called from another .c file. If that is the case, what is referencing a function?

Through the same website, they explain inline functions and I don't understand what it means.

The __inline keyword tells the compiler to substitute the code within the function definition for every instance of a function call. However, substitution occurs only at the compiler's discretion. For example, the compiler does not inline a function if its address is taken or if it is too large to inline.

Huh???

Any help is greatly appreciated, and I once again apologize for the terribly long post.

The following is located in file1.c (Using generic names as I don't think it matters)

COMPLEX cNoiseSample;
CGauss( &cNoiseSample, loopbackRadio->pState );

The following is located in file2.c

static inline void CGauss( COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState )
{
    //code
}
Summit answered 12/6, 2012 at 14:40 Comment(0)
W
17

static means it can't be referenced from another compilation unit (source file). "Referenced" means called, or otherwise referred to by name, e.g. assigned to a function pointer.

inline is a hint to the compiler that the function's code should be generated inline at the place it is called, rather than generated as a separate function to be branched to. This is normally done for performance reasons. To deal with Microsoft's quote:

the compiler does not inline a function if its address is taken or if it is too large to inline.

An inlined function has no address, since it doesn't exist as a separate entity. Its code is just intertwined seamlessly with the code it's called from. So, if you take the address of a function (e.g. to assign to a pointer) then the compiler has to generate it as a real function, and cannot inline it.

void means the function does not return a value.


Having looked at your code sample, I'd guess that there is a separate definition of CGauss() somewhere, which is being called from file1.c, whereas file2.c is calling its own private version. Either that, or file1.c is #includeing file2.c. Which would be nasty.

Woolgathering answered 12/6, 2012 at 14:44 Comment(5)
also, inline is necessary to enforce the one-definition rule when a function is defined in a header included in different compilation units (or at least this is the case for C++, don't know this detail exactly in C, I imagine it will be the same)Akerley
Well I guess I'm a little confused than @Graham-Borland. Let me show you why: COMPLEX cNoiseSample; CGauss( &cNoiseSample, loopbackRadio->pState ); /*This code is called at one point in a .c source file, and in a different .c source file I have this:*/ static inline void CGauss( COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState ) /*I apologize for the poor formatting in the comment box, wasn't sure how else to do this.*/Summit
It is #include-ing it. There is a lot of that in this code. Dealing with probably 200-250 source files and the same amount of header files (gotta love working on other people's code :)) Didn't even think about the #include function being the reason why it works.Summit
RE WHY you should use static: As a general rule of thumb, your code will be much easier to maintain if you make liberal use of static. It says to the maintainer "you're free to change this function w/o breaking anything outside this file". Any symbol (function or variable) that is not static can be referenced from literally anywhere. If you happen to be coming from an OOP language (C++, Java, etc), think of static functions (or global variables) as private and everything else as public. In addition, using static functions allow for more aggressive compiler optimization.Scauper
While static-functions can not be called from other translation units directly, you can pass a function pointer, which points to a static function, to a other translation unit and call this functions from there.Quartern
G
9

static only means something when you have more than one source file. It specifies that the static function or variable cannot be accessed from functions in a different file.

inline is a compiler optimization that speeds up your code in certain cases. Whenever you call a function, there is some overhead associated with it. So what the compiler can do is get rid of the function all-together by copy+pasting (almost) the inlined code.

Here's an example of inlining:

int dotproduct(int x1, int y1, int x2, int y2) {
    return multiply(x1,x2)+multiply(y1,y2);
}

inline int multiply(int a, int b) {
    return a*b;
}

The compiler will turn this into:

int dotproduct(int x1, int y1, int x2, int y2) {
    return x1*x2+y1*y2;
}

If you want to be fancy, you can also inline the dotproduct function ;)

Note that the inline keyword is simply a nudge to the compiler to inline certain functions. It may or may not actually do it depending on it's own judgement.

Gladwin answered 12/6, 2012 at 14:43 Comment(1)
Thanks @tskuzzy, inline makes a lot more sense now.Summit
K
3

The static keyword

Defining a C function static means (as the docs say) that this function can only be accessed from the source file it is defined in. The term 'reference' in this sence means either calling this function or for instance taking a function pointer to it.

Inlining

Normally, when you write a function in C, the compiler generates the machine code for this function:

foo:
   /* some machine code */
   ret

Every time you call this function, the compiler inserts an instruction such as

  call <foo>

into the caller's machine code, which means nothing else than "jump to foo, execute what you find there and when you encounter a ret instruction, return to this location."

In contrast, for inline functions, the compiler does not generate a separate function foo(), but instead inserts the machine code for function foo into every call site. When executing this code, this has the same effect.

So why do we do that? Inlining code has the advantage of saving you two jumps (the call and the respective ret), which makes your code execute a bit faster. As a downside, your code gets larger, because you insert the machine code on every call site instead of having only one copy of a callable function. That's why you usually only inline small functions.

Also, you cannot take function pointers to inline functions, and debugging becomes harder, because you cannot set a breakpoint on an inline function easily.

Therefore, inlining is left for the compiler as an optimization option and by using a keyword such as C++'s inline, your inline directive, or GCC's __attribute((inline)), you only give the compiler a hint that inlining might be worth a try here.

Kenwood answered 12/6, 2012 at 14:48 Comment(0)
E
1

I would like to add to all the above, before reading the above it is important to understand how c programming works. If you simply write open code, like

Setup(){
    int MainVar
}

MyRoutine(){
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

Then anyone can access MyRoutine.myVar1 directly from a second program. They could change the value of myVar2, (1. if it is not protected, 2. if they know it is there, 3. if they know what it does) before it is used in MyRoutine // Do stuff, thus changing what the original programmer intended.

Imagine you are writing a banking program and left the code vulnerable so someone could change the value of the DEPOSIT without changing the WITHDRAWL from the other bank in your routine. Someone else could come along and write a separate program to alter that value by 2, or 10, and create money where none existed. But if you precede the code, routine, method, or variables with STATIC Those items cannot be accessed, viewed and most importantly changed by another program.

You can use Static at any point, making entire routines CLOSED, or individual variables only CLOSED. Thus allowing others to make changes to certain aspects of your code, but preserving those aspects that need to be protected.

Putting Static at MyRoutine would prevent someone from executing MyRoutine from another program. Since MyVars are declared within MyRoutine, they would not be accessible from another program. But if there was a variable called MainVar declared elsewhere within the program, it would be accessible.

Setup(){
    int MainVar  // This can be accessed from outside this code
}

static MyRoutine(){  // Because of static these vars are not
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

And here, only the variables with static are protected. myVar3 could be read from elsewhere informing another routine that the exchange has completed.

Setup(){
    int MainVar    // This can be accessed from outside this code
}

MyRoutine(){
   static int myVar1;  // This can NOT be accessed from outside this code
   static int myVar2;  // This can NOT be accessed from outside this code
   bool myVar3;        // This can be accessed from outside this code
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}
Emancipation answered 20/5, 2018 at 20:59 Comment(0)
S
0

static just means that essentially the function is for all intents and purposes 'invisible' outside of the source file that it is defined in.

inline askes the compiler to essentially substite the function call code directly into the source at each place the function gets called at compile time (like a replacement of the function call with the code of the function) - however, it is not guaranteed to happen, it just suggests it to your compiler.

It is more technical than that and you are likely to get a far better answer, but in simple language this is what the terms mean.

Schoonover answered 12/6, 2012 at 14:46 Comment(0)
U
-2

It is so simple.

void* can return a void pointer (any reference). But void can not return any thing.

For example:

1)

int x=7;

void *abc()    
{    
    return &x;    
}     

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

Output: 7

2)

int x=7;

void abc()    
{    
    return &x;    
}

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

It will produce compilation error at printf("%d\n",*((int*)(abc())));

Because void can't return anything.

Ursula answered 6/1, 2019 at 0:39 Comment(1)
Please replace "printf("%d\n",((int)(abc())));" to "printf("%d\n",*((int)(abc())));", Its a typo errorUrsula

© 2022 - 2024 — McMap. All rights reserved.