0

I am learning C and would like to ask about best practices.

Here two implementations (shirt is struct):

implementation1 :

void printShirt(shirt shirt){
    printf("(%d , %s)",shirt.size,shirt.color);
}
void printShirts(shirt * shirts, int nbShirts){
    int i;
    for(i=0;i<nbShirts;i++) printShirt(shirts[i]);
    printf("\n");
}

implementation 2:

void printShirt(shirt * shirt){
    printf("(%d , %s)",shirt->size,shirt->color);
}
void printShirts(shirt * shirts, int nbShirts){
    int i;
    for(i=0;i<nbShirts;i++) printShirt(&shirts[i]);
    printf("\n");
}

If I am correct (?), in implementation 1 the data of each shirt is copied from heap to stack before print. But this does not happen in implementation 2 (?).

For big arrays and structure might this have an impact ? Is there some best practice to follow ?

trincot
  • 317,000
  • 35
  • 244
  • 286
Vince
  • 3,979
  • 10
  • 41
  • 69

2 Answers2

4

Yes, this can have an impact on large structures, or large arrays of smaller structures, unless the compiler is able to optimize the call away. It's far more normal to avoid copying data when you already have a copy of it - especially if you aren't intending to modify the copy.

Copying a struct is quite fast - it essentially just blits bytes from one location in memory to another... But copying a pointer is faster. If the struct is small, you might consider copying it so that you avoid extra pointer dereferencing. However, by now you may well be getting into premature optimization.

Back to the pointer approach, normally you help the programmer to realise that the data will not be modified by receiving a const pointer:

void printShirt( struct shirt const * shirt )

Your example is a bit naive, because the cost of printf is far greater than copying even a relatively large structure. But I understand what you're trying to ask.

paddy
  • 60,864
  • 6
  • 61
  • 103
  • So there is a tradeoff to find ? data copying vs dereferencing ? – Vince Oct 25 '13 at 02:18
  • Yes, but there are almost always larger bottlenecks in your code than that one. And it's platform-specific (*eg* 64-bit pointers vs 32-bit pointers). Hence I mentioned *premature optimization*. 99.99% of the time, you'll want to pass structures by pointer. – paddy Oct 25 '13 at 02:23
  • just to make sure I really get it, in any code "d[i]=5" and "&d[i]->5" do the exact same thing (not from a result view point, from a memory management view point) ? (here my point is not to optimize my code, just to make sure I get the main principle right). – Vince Oct 25 '13 at 02:47
  • Passing the pointer as `&shirts[i]` or `shirts+i` is correct. I don't understand what you mean by `&d[i]->5` - that would be a syntax error. Did you mean `d[i].color` *vs* `(&d[i])->color`? Then yes, they access the same memory. Unless the compiler can optimize it away (like in this trivial example), the reference operator `&` and the struct dereference operator `->` will take additional cpu cycles, so they're not *exactly* the same. – paddy Oct 25 '13 at 02:56
-1

You will use less memory the implementation 2 since you only pass in the address (pointer) to the printShirt function. Implementation 1 could be slow if sizeof shirt is big and it will also consumes more memory since you're going to copy all fields in the struct.

marcadian
  • 2,608
  • 13
  • 20