views:

61

answers:

3

In GCC, I'm able to do this:

(CachedPath){ino}
inode->data = (struct Data)DATA_INIT;

where:

struct CachedPath
{
    Ino ino;
};

typedef int8_t Depth;
struct Data
{
    Offset size;
    Blkno root;
    Depth depth;
};
#define DATA_INIT {0, -1, 0}

MSVC gives the following error for these kind of casts:

error C2143: syntax error : missing ';' before '{'

How can I do this in MSVC? Further note that the code has been converted from C99, where I used designated initializers for this, and then cast it similarly. Any clarity on how these various features relate between C99, and MSVC/GCC implementations of C++ is appreciated.

A: 

MSVC is not conformant to C99 and only loosely conformant to previous versions of the C standard. I know no way to do what you want syntactically with MSVC, but the same effect can be obtained by using static const structs instead of anonymous compound literal constants, and local struct variables that are initialized with the correct values instead of anonymous compound literals that are nonconstant.

The idea behind this approach is that a C99 compound literal is (at least nearly) equivalent to a local variable of the same type at the same scope, initialized with the contents of the braces. Using static const structs in the case where the data is constant is just an optimization (it will likely produce smaller/faster code than the C99 compound literal approach).

R..
MSVC is very precisely conformant to C89/90 standard. What is the strange claim of being "loosely conformant" based upon?
AndreyT
Most of the conformance problems I know about are the standard library and related to internationalization amendments ("C95" I think it's typically called). For instance, incorrect behavior of the `%s` and `%ls` format specifiers in `wprintf` and `printf`, respectively, and the use of multi-`wchar_t` characters (UTF-16) in ways that breaks the C multibyte/wide conversion API. I suspect the compiler/compilation environment itself has some bugs too though - like keyword/function/type names that conflict with those reserved for the application.
R..
What do you mean by "use static const structs"?
Matt Joiner
Along with `#define DATA_INIT {0, -1, 0}`, use `static const struct Data data_init = DATA_INIT;`, and then use the latter for assignments and the former for initializations.
R..
@R.. Very nice, I hoped as much.
Matt Joiner
A: 

MSVC is a mix of standards, and is not fully compliant with most of them, thus, you'll probably need to use a default initializer/constructor, like so (C++ way):

#define DATA_INIT 0,-1,0
inode->data = Data(DATA_INIT);

struct Data
{
    Offset size;
    Blkno root;
    Depth depth;

    Data(Offset size, Blkno root, Depth depth) : size(size), root(root), depth(depth)
    {
    }
};
Necrolis
This is not remotely C code.
R..
@R.. please read the tags and the OP's post, this is C++ code, like the OP requested
Necrolis
OK, reverted the -1. Sorry.
R..
You've forgot to define a constructor accepting 3 parameters for `struct Data`.
atzz
@atzz: good catch, I'll add that, though I remember that MSVC could auto initialize without one, can't test that at the moment though
Necrolis
Yes, this would be great if C++ created a default constructor accepting all the members of the struct in order.
Matt Joiner
+2  A: 

The construct (Type){initialisers} is not a cast operation, but it is the syntactic construct of a compound literal. This is a C99 construct, which GCC also supports in its C++ compiler as an extension. As far as I can determine, compound literals are not supported by MSVC in either its C or C++ mode.

The alternatives for this construct are

  • Explicitly declare and initialise a temporary object of the desired struct type and use that instead of the compound literal in the assignment
  • Instead of doing a single assignment with the compound literal, use a separate assignment for each individual member.
Bart van Ingen Schenau
+1 better-written than my answer
R..