Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a compiler allowed to remove assignments to struct member if it is not obviously used?

Consider the following code:

char buffer[256];

struct stX
{
    int a;
    int b;
    int c;
};

void * my_memcpy ( void * destination, const void * source, size_t num );

int main()
{
    struct stX x;
    x.a = 1;
    x.b = 2;
    x.c = 3;
    my_memcpy(buffer, &x.b, 2 * sizeof(int));
    {
        int i;
        for (i = 0; i < 2 * sizeof(int); ++i) {
            printf("%d\n", buffer[i]);
        }
    }
    return 0;
}

A particular compiler for embedded systems decides to remove the assignments to x.a and x.c (since they are never used (at least not obviously)). Is this an optimization the c standard allows?

Of course, defining the structure instance as volatile leads in the assignment being included.

gcc and msvc do not perform this optimization (but this is not really a reasoning).

Update: As some answers (correctly) assumed, the compiler could optimize due to the known definition of memcpy, however, this is not what my particular implementation does. (It reserves the memory for the struct on the stack, just does not perform the assignments.) Let's assume we replaced the memcpy with a function for which the compiler has no definition available. Also, let's assume the buffer is used after the function call. I updated the sample code above accordingly.

like image 215
user2011348 Avatar asked Jan 25 '13 15:01

user2011348


1 Answers

Yes, the compiler is free to do anything so long as the observable behaviour of the application is unaltered.*

But this assumes that you have a conforming program, i.e. one with well-defined behaviour. Your code doesn't exhibit well-defined behaviour; it is not valid to access x.c by dereferencing a pointer to x.b (which is what you're implicitly asking memcpy to do).

Update: The paragraph above may not be correct; please see the discussion in the comments...


* For a more stringent definition, see section 5.1.2.3 of the C99 standard:

Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment.

...

An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced

like image 192
Oliver Charlesworth Avatar answered Nov 03 '22 06:11

Oliver Charlesworth