5

I wrote the following code to play with a specific C11 idiom of anonymous structs described in the book "21st Century C".

#include <stdio.h>
#include <math.h>


typedef struct Price {
  double close;
  double high;
  double low;
} Price;

typedef struct OLHC {
  union { //union allows the dual benefits of the seamless anon. struct and code-reuse
    struct Price;  //an anonymous struct but not explicitly re-defined
    Price p;
  };
  double open;
} OHLC;


double range(Price p){  //behaviour defined for struct Price
  return(p.high - p.low);
}

double travelRange(OHLC p){  //re-uses behaviour defined for struct Price
  return (fabs(p.open - p.low) + range(p.p) + fabs(p.high - p.close));
}

int main(){
  OHLC msft={.close=33.4,  //seamless access to members
         .open=32.1,
         .high=35.5,
         .low=30.23};
  printf("Today's travel Range for MSFT was %f\n",travelRange(msft));
}

I can get it to compile without warnings with either gcc48 or gcc49 as follows:

gcc-4.9  -std=c11 -fms-extensions -lm -o c11 c11.c

I can also get it to compile and run on my OS X mavericks macbook with one warning:

cc -std=c11 -fms-extensions -lm -o c11 c11.c

The warning is:

c11.c:19:5: warning: anonymous structs are a Microsoft extension[-Wmicrosoft]

Is there any version of gcc or clang which will compile this file with just the std=c11 flag without warnings. Are anonymous structs/unions part of C11 standard and just not implemented yet or are they as used above not conformant?

EDIT: Just to clarify the code above is designed to allow the reuse of code written for the base structure but at the same time get the benefits of the seamless access to all members of the derived structure containing the original structure anonymously. This is accomplished with the union of an anonymous struct and its corresponding named type. Too bad this is not conforming as I thought it was a really nice little idiom.

mcheema
  • 850
  • 9
  • 25
  • possible duplicate of [How to use anonymous structs / unions in C?](http://stackoverflow.com/questions/1972003/how-to-use-anonymous-structs-unions-in-c) –  Nov 20 '13 at 23:04
  • They *are* standard, see the duplicate. –  Nov 20 '13 at 23:04
  • Thanks for the link to the duplicate but the anonymous struct used above is different from the one in that question and I guess now based on the answer below it is not conformant. – mcheema Nov 20 '13 at 23:47
  • So after all, you aren't really asking about the anon struct, but about the weirdly-scoped forward declararion... Okay... –  Nov 20 '13 at 23:49
  • @h2co3 I edited title and question to reflect this. – mcheema Nov 21 '13 at 00:21

2 Answers2

3
typedef struct OLHC {
  union {
    struct Price;
    Price p;
  };
  double open;
} OHLC;

is not C11. It is C with extensions and is only allowed in gcc with -fms-extensions option.

C11 has anonymous structures and unions but the:

    struct Price;

in you struct OLHC is not allowed as a part of C11 anonymous structures.

Is there any version of gcc or clang which will compile this file with just the std=c11 flag without warnings.

No, C requires at least a warning.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • I guess the writer of 21st Century got that wrong. My example is based on his which he claims will compile once compilers fully implement c11. Thanks for the reply. – mcheema Nov 20 '13 at 23:44
  • 1
    any way to suppress the warning from clang when I have given it the -fms-extensions flag. After all in this case I have requested the extension explictly so why the warning? – mcheema Nov 21 '13 at 10:31
  • Yes, is there any way to suppress this one warning? – Engineer Apr 30 '16 at 10:08
  • 1
    I agree that the warnings are stupid given the explicit flag given, and filed a bug report to Clang about it; but they confirmed that the warnings are purposefully there, to warn about the non-standard struct (you don't say!). Anyway, the warnings can be suppressed like most (all?) other warnings: with -Wno-. In this case, with -Wno-microsoft. – hmijail Dec 11 '16 at 11:37
2

To add to ouah's answer I re-worked the code to allow compilation with just the -std=c11 flag:

#include <stdio.h>
#include <math.h>        

typedef struct Price2 {
  double close;
  double high;
  double low;
} Price2;

typedef struct  {
  union {
    struct {  // Price2 equivalent textually re-defined within OLHC2
      double close;
      double high;
      double low;
    };
    Price2 p;
  };
  double open;
} OHLC2;


double range2(Price2 p){  //behaviour defined for struct Price2
  return(p.high - p.low);
}

double travelRange2(OHLC2 p){  //behaviour for struct Price2 re-used by OHLC2
  return (fabs(p.open - p.low) + range2(p.p) + fabs(p.high - p.close));
} 

int main(){

  OHLC2 msft2={.close=33.4,
         .open=32.1,
         .high=35.5,
         .low=30.23};
  printf("Today's travel Range for MSFT was %f\n",travelRange2(msft2));

}

The key unsatisfyingly is to replace the reference to the base structure in the derived structure by cutting and pasting the base struct definition sans tag and everything works. This seems to obviate some of the benefits of code re-use that works much better with the Microsoft extension switch.

mcheema
  • 850
  • 9
  • 25