0

I'm planing use Structs containing an scalar field in my C Code, to do some semantic strong typing. The basic idea is macros for cheap "operations", that will fail on wrongly named struct fields, and of course more complex functions by strict parameter list.

Examples (Only the basic Idea - not exspecially clever macro code)

typedef struct {float32_t speedval} MySpeed_t;
typedef struct {float32_t timeval} MyTime_t;
typefed struct {float32_t accvalue} MyAcceleration_t;

#define ACC_VEL_DT(acc,vel,time)\
          (((acc).accvalue = (vel).speedval / (time).timeval)), (acc))

#define ADD_SPEED(velres, vel1, vel2) \
           (((velres).speedval = (vel1).speedval + (vel2).speedval), (velres))

unint8 someCleverMathAndCheck(MySpeed_t speed, MySpeed_t speedArr[], MyAcceleration_t);

Now what do I have to expect from a compiler when handling such onelement structures? Must I expect some padding, more complex asm for "dereferencing the first element", or horrible things when using those constructs as function parameters? What does the standard say about?

Mark A.
  • 579
  • 4
  • 13
  • 1
    I believe the details of padding and access is implementation defined. Though structure wise I think the standard implies that the address of the struct is the same as the address of the first member of the struct. I leave it up to the language lawyers to answer this since I'm not 100% sure. – slebetman Aug 01 '14 at 07:25
  • The standard says nothing at all about how efficient the generated assembly must be. You could try it on your system and see what happens. – M.M Aug 01 '14 at 07:38

2 Answers2

4

There won't be any extra padding. From the standard, the address of a struct is the address of its first element, hence padding is always inserted between elements or at the end of the struct, never at the beginning. Further, you won't have to worry about extra padding at the end, because the alignment will be exactly the alignment required for the (single) data type.

With optimizations turned on, you can expect the compiler to produce basically the same assembly code. For example, the code produced by (32bit) GCC at O2 for:

float add(float a, float b)
{
    return a + b;    
}

looks like:

_add:
LFB0:
    .cfi_startproc
    flds    8(%esp)
    fadds   4(%esp)
    ret
    .cfi_endproc

If you instead define something like:

typedef struct foo
{
    float x;
} foo;

foo add(foo a, foo b)
{
    foo f; 
    f.x = a.x + b.x;
    return f;
}

and compile that with O2, the assembly is exactly the same.

Yuushi
  • 25,132
  • 7
  • 63
  • 81
  • I think he's expecting some explanation about padding in-depth as well, so I guess that would make your answer even more complete :) –  Aug 01 '14 at 07:38
  • The in deep padding information I can extract easily from many other information. Unexpected padding is on example of things that I might happen to be not aware of. If there a no issues tu expect, besides horrible looking macro code, I am fine with that answer. – Mark A. Aug 01 '14 at 08:16
0

I'm not entirely sure what you are worried about happening, but I believe padding varies based on the operating system. Don't quote me. However it is definitely not something you need to worry about unless you're doing some sketchy size computations for custom memory fiddling. Accessing a member variable shouldn't take longer than any normal variable. It's essentially just pointer addition at an extraordinarily low level, except you're adding 0 so it stays the same. I'm not sure what you mean by "horrible things", but as long as you don't make typos it should work.

  • I also don't know what I mean. I ask for the issues I might not be aware of :-) and this pattern might raise. If you don't see some, I am perfectly ok with it. Thanks for the answer. – Mark A. Aug 01 '14 at 08:17