1

If I write this code in a function:

void func(void)
{
    int x = 0;
    int y = 3724832+x;
}

It would (probably) optimize the variable y out because it isn't being used. Even if I'm wrong about this specific case, the point I'm making is that the compiler has the ability to optimize out variables.

My question is does it also do this with local arrays?

Example:

void func(void)
{
    uint8_t tempBuffer[2] = {0x00, 0x01};
    sendBufferOverUSB(tempBuffer, 2); //sendBufferOverUSB(uint8_t* arr, int sizeArr);
}

Does the compiler then optimize this array out? Or does it keep this array in memory forever? Or is that even what optimization means? I know that arrays are created at compile time, so I'm trying to figure out if I should be using arrays in the way I've just used them or if I should make an array for every .c file as a buffer and simply use that whenever I need to store some bytes for transmission. Like this:

//example.c
#include "example.h"
#define MAX_EXAMPLE_BUFFER_SIZE 256
static uint8_t localBuffer[MAX_EXAMPLE_BUFFER_SIZE];
void func(void)
{
    // using buffer 
    localBuffer[0] = 0x00;
    localBuffer[1] = 0x01;
    sendBufferOverUSB(localBuffer, 2); //sendBufferOverUSB(uint8_t* arr, int sizeArr);
}

I am going to have a bunch of functions which need to convert from Little Endian variables into Big Endian formatted bytes so i essentially need some buffer to move these bytes into, and I just didn't know if making an array of the size needed was better than using a buffer for that .c file.

7
  • 2
    It would be easy enough to find out. Just compile the above code using GCC with assembly output, and play with the compiler's optimization flags. Commented Jul 3, 2019 at 19:41
  • For what it's worth, uint8_t tempBuffer[2] = {0x00, 0x01}; is declared in a function locally, so it will be stored on the stack while the function executes, and gets popped off the stack (discarded) when the function exits. Commented Jul 3, 2019 at 19:45
  • @RobertHarvey Ok so then it'd probably be best for me to do this locally. Thanks!
    – user340139
    Commented Jul 3, 2019 at 19:48
  • Yes, that would be my guess. Commented Jul 3, 2019 at 19:49
  • 1
    godbolt.org You can try many different compilers online there, very easy to write simple tests for things like this. Check it out!
    – Erik Eidt
    Commented Jul 3, 2019 at 20:08

3 Answers 3

3

"Optimized out" means the compiler realises the variable isn't necessary, and deletes the variable. For example, this code:

void func(void)
{
    int x = 0;
    int y = 3724832+x;
    printf("%d\n", y);
}

might be compiled the same way as:

void func(void)
{
    printf("%d\n", 3724832);
}

or even (if your compiler is smart enough)

void func(void)
{
    puts("3724832");
}

and we would say that the variables x and y have been optimized out, because the optimizer has removed them from the program.

"Optimized out" does not mean that the variable gets destroyed when the function returns. All non-static local variables get destroyed when the function returns. No exceptions. This includes arrays.

In your function:

void func(void)
{
    uint8_t tempBuffer[2] = {0x00, 0x01};
    sendBufferOverUSB(tempBuffer, 2);
}

the variable tempBuffer will be destroyed when the function returns. If you try to trick the compiler so you can use tempBuffer after func returns - for example, using a pointer - you might find that the memory that used to contain this variable has been overwritten, and it no longer contains {0x00, 0x01}. You might even get a crash when you try to use it. This isn't because of optimization.

0

In your specific example, no, the array would not be optimized out because it gets used in the code (its address gets passed to sendBufferOverUSB).

I know that arrays are created at compile time

Nothing's created at compile time. When you run the program, anything declared at file scope (outside the body of a function) or with the static keyword is created when the program is loaded and released when the program exits (those objects have static storage duration). Objects with auto storage duration are created when their enclosing block is entered and released when that block is exited1. Objects with allocated storage duration are created by a call to malloc/calloc/realloc and released by a call to free2.

In the code

void func(void)
{
    uint8_t tempBuffer[2] = {0x00, 0x01};
    sendBufferOverUSB(tempBuffer, 2); //sendBufferOverUSB(uint8_t* arr, int sizeArr);
}

tempBuffer has auto storage duration - it only exists for the lifetime of its enclosing function. Space for tempBuffer is set aside on function entry and released on function exit (meaning if you try to return a pointer to that array, that pointer is not valid after the function exits). By contrast, in the code

void func(void)
{
    static uint8_t staticBuffer[2] = {0x00, 0x01};
    sendBufferOverUSB(staticBuffer, 2); //sendBufferOverUSB(uint8_t* arr, int sizeArr);
}

staticBuffer has static storage duration - space for it is set aside on program startup and released on program exit, and the initialization is only performed once at program startup.


  1. Logically speaking, anyway. It's common practice to allocate space for all auto variables at function start and release it at function exit, regardless of whether those variables are limited to an inner scope.
  2. There's also a thread storage duration, but I don't have enough experience with it to say anything meaningful about it.

0

Does the compiler then optimize this array out?

Probably not, because you're passing it to a function, which almost certainly means it is decaying to a pointer in the argument list. Taking the address of an object is one way to force the compiler to materialize it (ie, prevent elision).

If sendBufferOverUSB happens to be inlined, the optimizer will work on the inlined block, and may again be able to prove the array isn't used, or that its address never leaves the inlined scope and that it can be replaced with literal values.

Or does it keep this array in memory forever? Or is that even what optimization means?

No, the array is automatic and only exists for the duration of this function anyway. The values to which the array is initialized will either be expressed as literals in the code, or there will be a static object somewhere copied into your local array. Anyway, the values 0x00 and 0x01 need to exist somewhere.

or if I should make an array for every .c file as a buffer

no, definitely don't use globals.

Mostly because they prevent later use of threading and re-entrancy, but they may also have a performance penalty (eg. an indirect load via the Global Offset Table or similar).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.