Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't C code compile properly in Visual Studio?

When trying to compile some C code in Visual Studio, I often get numerous errors. The reason for this problem is Visual Studio's C compiler only supports an old version of C. How can I quickly fix all of my C code to be compatible with the Visual Studio compiler?

For example, I'm trying to compile websocket.c and associated headers—from http://libwebsockets.org/trac/libwebsockets. I'm getting a lot of errors about "illegal use of this type as an expression" which, according to other answers, indicates that I need to move my variable declarations to the beginning of every block.

like image 384
Christian Stewart Avatar asked Jan 10 '14 06:01

Christian Stewart


1 Answers

The problem with compiling C in Visual Studio

Visual Studio does not provide full support for ANSI C. If you want C code to be portable enough to compile with Visual Studio, you'll probably have to target C89 or have it compile as C++ code. The first option is unnecessarily restrictive, unless for some reason you really really love the '89 standard C and you hate all of the new features of later standards.

Compiling as C++

The second option, compiling as C++, can be achieved, as dialer mentions in his comment, by changing the target language type. You can do this by right-clicking the source file(s), and selecting Properties, navigate to C/C++ -> Advanced and changing the Compile As option to Compile as C++ code.

You can also specify the source file type as C++ by using the /Tp <filename> switch on the command line, or use the /TP switch to compile everything as C++.

Problems with Linking

If you're linking to a library written in C, the above fix can cause linking to fail. This is because, now that you're compiling your C files as C++, the function names will be mangled. When the compiler adds the library and tries to match the name of the function you called to one exported by the library, it will fail because the name exported by the library will not be mangled.

To combat this problem, C++ allows you to specify that specific names are exported with "C" linkage, which tells the compiler that the names are not mangled. This is usually done by prefixing the function declaration with extern "C", or placing everything in a block of

extern "C" {
    /* header contents here */
}

Well-disciplined C library developers know about this problem and will use techniques, such as macros, to combat it. A common technique is to detect when the user is compiling as C++, and place macros similar to these at the beginning and end of a block of declarations in a header file:

#if defined (__cplusplus)
#define BEGIN_EXTERN_C extern "C" {
#define END_EXTERN_C }
#else
#define BEGIN_EXTERN_C 
#define END_EXTERN_C 
#endif

If you're using well-established and well-coded C libraries, the headers probably contain something similar to this. If not, you might need to do it yourself (and if the library is open-source, submit the changes as a patch!)

The future of C in Visual Studio

There is an MSDN blog post from July 2013, which announced that a large number of C99 features have been implemented for Visual Studio 2013. Part of the reason for this seems to be that the features are mentioned in parts of some C++ standards, so they would be required anyway. The new features include new math.h functions, new inttypes.h types and more. See the post for a full list.

An earlier post gives the following tidbits:

Additionally, some C99 Core Language features will be implemented in 2013 RTM:

  • C99 _Bool
  • C99 compound literals
  • C99 designated initializers
  • C99 variable declarations

Note that there are features missing, including:

  • The tgmath.h header is missing. C compiler support is needed for this header.
    • Note that the ctgmath header was added—this is possible because that header does not require the tgmath.h header—only the ccomplex and cmath headers.
  • The uchar.h header is missing. This is from the C Unicode TR.
  • Several format specifiers in the printf family are not yet supported.
  • The snprintf and snwprintf functions are missing from stdio.h and wchar.h.

Although you can expect them in the future:

We don't hate snprintf() (quite the contrary), we just missed it and ran out of time.

Note that other language features that don't have to do with the standard library are still not available.

It looks like standard C will receive more support in the future, although probably just because the implementation of more modern features is necessary to support C++11 and C++14.

<tgmath.h> and its associated compiler magic are special and I don't know our plans for them (as Pat's post explained, C++ has overloading/templates and doesn't need C compiler magic).

like image 104
Anthony Avatar answered Oct 10 '22 22:10

Anthony