Is there a difference in the transfer rate of a pointer or const structure

In C, structures are often passed by pointers to prevent a lot of data copying.

I wonder if it really matters Don't compilers prevent unnecessary copies?

For example, if I mark the variable const, will the compiler optimize the copy?

Example

struct my_t {
    int a;
    int b[24];
}

int generate_updated_myt(const my_t c) {
    // do something with c
    return 0;
}

int generate_updated_myt(const my_t * c) {
    // do something with *c
    return 0;
}

      

Will there be any difference in speed between the two?

+3


source to share


2 answers


If I understand the question correctly, you are asking if the compiler can optimize

int generate_updated_myt(const my_t c);

      

so that the calls will generate_updated_myt()

actually pass a pointer instead of an actual copy of the object (i.e. it can act similarly to C ++ const&

).

Consider the following contrived example, if the local copy c

was accessed as a reference to the passed object instead of the actual copy:



#include <stdio.h>

struct my_t {
    int a;
    int b[24];
};

int foo(void);
int generate_updated_myt(const struct my_t c)
{
    int a = c.a;

    foo();  // if c is really a 'pointer' to the passed in object,
            //     then this call to `foo()` may change the object
            //     c refers to.

    if (a != c.a) {
        puts("how did my private copy of `c.a` get changed?");
    }

    return a;
}

struct my_t g_instance;

int main(void)
{
    generate_updated_myt( g_instance);
    return 0;
}

int foo(void)
{
    int counter = g_instance.a++;

    return counter;
}

      

This is one of the reasons the suggested optimization is not allowed.

And that doesn't even take into account, which is const

very easily discarded (even if it might be in bad shape).

+3


source


This will depend on the calling convention, the size of the structure, whether the corresponding cache and TLB entries are filled and what you do with it. It is very difficult to answer in general, although microarchitectural functions such as renaming registers will do their best to make small differences.



The only big difference I can think of that I have come across such a design decision is that if generate_updated_myt contains some sort of possibly-vectable loop that works in c, declaring it const is probably not enough. You may not get vector output unless it declares something likeconst my_t * restrict c __attribute__((aligned(64)))

+1


source







All Articles