If I understood correctly, the article https://en.cppreference.com/w/cpp/language/aggregate_initialization says that designated initialization is allowed starting from c++20, and is not allowed in c++11.
So why is the following compiled in c++11? g++ -std=c++11 main.cpp
struct A { int x; int y; int z; };
int main(int argc, char const *argv[])
{
A b{.x = 1, .z = 2};
return 0;
}
My first guess was that there is some kind of gcc extension that supports it, but clang compile this code as well (clang -std=c++11 main.cpp)
Why is designator initialization compiled in c++11?
The program is ill-formed in C++11. The C++ language doesn't disallow ill-formed programs from compiling.
My first guess was that there is some kind of gcc extension that supports it, but clang compile this code as well
Your first guess is good, and you can simply expand it to arrive at the answer: The language is extended by both GCC and Clang. Clang often attempts to be as compatible with GCC as possible. For better and for worse.
Related
I am extending a project which compiles some libraries with c99 and one library with c++11 and uses complex.h complex numbers in the c99 library.
I know this may be a stupid idea but it wasn't mine and I need to make it work somehow.
The code does not compile with gcc4.9 and -std=c++11 and I am quite clueless what to do. How do I make this snippet compile?
#include <complex.h>
#include <cstdio>
int main(int argc, char * argv[]) {
double _Complex a = 3.0 + 0.0 * _Complex_I;
//printf("%lf\n", creal(a));
return 0;
}
Gives the error
In file included from /usr/local/include/c++/7.1.0/complex.h:36:0,
from main.cpp:1:
main.cpp: In function 'int main(int, char**)':
main.cpp:5:33: error: unable to find numeric literal operator 'operator""iF'
double _Complex a = 3.0 + 0.0 _Complex_I;
^
main.cpp:5:33: note: use -std=gnu++11 or -fext-numeric-literals to enable more built-in suffixes
main.cpp:5:33: error: expression cannot be used as a function
double _Complex a = 3.0 + 0.0 _Complex_I;
^
main.cpp:5:19: warning: unused variable 'a' [-Wunused-variable]
double _Complex a = 3.0 + 0.0 _Complex_I;
with
g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
-std=gnu++11 works it seems, but is there a way to make it work with -std=c++11?
How to compile c complex numbers with c++11
You don't. Standard C++ does not support the <complex.h> C library header.
Either:
Use the GCC language extensions.
Implement a wrapper function for anything that deals with C complex numbers that provides an interface which doesn't use C complex numbers. Implement the wrapper in C and use the wrapper from C++.
Don't use C complex numbers in the first place - use std::complex instead.
I have spent the day searching for an answer to what should be a simple problem. I am building a c++ program to call a fairly large amount of existing fortran. I started by changing the fortran main to a subroutine and then called it with a simple c++ main. My steps look like:
gfortran -c f1.f90 f2.f90 ......
g++ -c mn.cpp
gfortran -lstdc++ -o prog.exe mn.o f1.o ....
mn.cpp started out looking like the code below, and the above steps do work ok. I get a host of linker errors if I try to link with:
g++ -lgfortran (this never works!)
Next, I tried to instantiate a simple array class (remove the 2 commented lines). This produced linker errors concerning gxx_personality_seh0, vtable, and operator new.I get similar errors if I just create an array of doubles with new (remove comment), and if I remove the call to the fortran program completely (still linking with gfortran). Obviously, -lstdc++ does not bring in all the libraries needed. Which libraries are needed and how can I get it to link them?
I am using Windows 7 with Cygwin. The libraries it links are in ...lib/x86_64-pc-cygwin/4.9.3. I can post the linker output if it would be helpful.
mn.cpp which works (code commented out) is below:
#include <string.h>
#include <stdlib.h>
//#include "array.h"
extern "C" {
void mnf90_(const char*,int);
}
int main(int argc, char* argv[]){
// Array2D A; // first derivative
static const char *feos = "d/fld9x.dat";
int npoint = 20;
// double *xc = new double[npoint];
mnf90_(feos,strlen(feos));
}
The line of code below is giving an error with the gcc compiler even when this file is saved as check.c. The error is at the line void swap_address(int& a, int& b) as
error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
I have used this command to compile the C file: gcc -o check check.c
but the same code is working fine if I use the g++ compiler using: g++ -o check check.c
Please provide me with the reason why it is working for g++ and not for gcc.
The code:
#include <stdio.h>
void swap_value(int a, int b)
{
a=a+b;
b=a-b;
a=a-b;
}
void swap_address(int& a, int& b)
{
a=a+b;
b=a-b;
a=a-b;
}
int main()
{
int i=5,j=3;
swap_value(i,j);
printf("%d%d\n", i, j);
swap_address(i,j);
printf("%d%d\n", i, j);
return 0;
}
swap_address() has reference parameters the file has a ".c" extension, so gcc is assuming it is a C file and producing an error because reference parameters are not part of C.
g++ is taking the file as being C++, so it is happy with the reference parameters.
References are a C++ feature, they are not supported in C.
C and C++ are different programming languages.
You saved your file with .c extension, which makes gcc executable to treat it as C language file. Meanwhile you attempt use C++ features in your code (e.g references). No wonder it doesn't compile with gcc.
g++ executable unconditionally treats all files as C++ files, regardless of extension, which is why it compiles with g++.
Take this sample code:
#include <string.h>
#define STRcommaLEN(str) (str), (sizeof(str)-1)
int main() {
const char * b = "string2";
const char * c = "string3";
strncmp(b, STRcommaLEN(c));
}
If you don't use optimizations in GCC, all is fine, but if you add -O1 and above, as in gcc -E -std=gnu99 -Wall -Wextra -c -I/usr/local/include -O1 sample.c, strncmp becomes a macro, and in preprocessing stage STRcommaLen is not expanded. In fact in resulting "code" strncmp's arguments are completely stripped.
I know if I add #define NEWstrncmp(a, b) strncmp (a, b) and use it instead, the problem goes away. However, mapping your own functions to every standard function that may become a macro doesn't seem like a great solution.
I tried finding the specific optimization that is responsible for it and failed. In fact if I replace -O1 with all the flags that it enables according to man gcc, the problem goes away. My conclusion is that -O1 adds some optimizations that are not controlled by flags and this is one of them.
How would you deal with this issue in a generic way? There may be some macro magic I am not familiar with or compiler flags I haven't looked at? We have many macros and a substantial code base - this code is just written to demonstrate one example.
Btw, GCC version/platform is gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5).
Thanks,
Alen
You correctly noted that
in preprocessing stage STRcommaLen is not expanded
- more precisely, not before the strncmp macro gets expanded. This inevitably leads to an error you probably overlooked or forgot to mention:
sample.c:7:30: error: macro "strncmp" requires 3 arguments, but only 2 given
Your conclusion
that -O1 adds some optimizations that are not controlled by flags and
this is one of them
is also right - this is controlled by the macro __OPTIMIZE__ which apparently gets set by -O1.
If I'd do something like that (which I probably wouldn't, in respect of the pitfall you demonstrated by using sizeof a char *), I'd still choose
mapping your own functions to every standard function that may become
a macro
- but rather like
#include <string.h>
#define STRNCMP(s1, s2) strncmp(s1, s2, sizeof(s2)-1)
int main()
{
const char b[] = "string2";
const char c[] = "string3";
STRNCMP(b, c);
}
I have some C++0x code. I was able to reproduce it below. The code below works fine without -std=c++0x however i need it for my real code.
How do i include strdup in C++0x? with gcc 4.5.2
note i am using mingw. i tried including cstdlib, cstring, string.h and tried using std::. No luck.
>g++ -std=c++0x a.cpp
a.cpp: In function 'int main()':
a.cpp:4:11: error: 'strdup' was not declared in this scope
code:
#include <string.h>
int main()
{
strdup("");
return 0;
}
-std=gnu++0x (instead of -std=c++0x) does the trick for me; -D_GNU_SOURCE didn't work (I tried with a cross-compiler, but perhaps it works with other kinds of g++).
It appears that the default (no -std=... passed) is "GNU C++" and not "strict standard C++", so the flag for "don't change anything except for upgrading to C++11" is -std=gnu++0x, not -std=c++0x; the latter means "upgrade to C++11 and be stricter than by default".
strdup may not be included in the library you are linking against (you mentioned mingw). I'm not sure if it's in c++0x or not; I know it's not in earlier versions of C/C++ standards.
It's a very simple function, and you could just include it in your program (though it's not legal to call it simply "strdup" since all names beginning with "str" and a lowercase letter are reserved for implementation extensions.)
char *my_strdup(const char *str) {
size_t len = strlen(str);
char *x = (char *)malloc(len+1); /* 1 for the null terminator */
if(!x) return NULL; /* malloc could not allocate memory */
memcpy(x,str,len+1); /* copy the string into the new buffer */
return x;
}
This page explains that strdup is conforming, among others, to the POSIX and BSD standards, and that GNU extensions implement it. Maybe if you compile your code with "-D_GNU_SOURCE" it works?
EDIT: just to expand a bit, you probably do not need anything else than including cstring on a POSIX system. But you are using GCC on Windows, which is not POSIX, so you need the extra definition to enable strdup.
add this preprocessor "_CRT_NONSTDC_NO_DEPRECATE" to Project Properties->C/C++ Build->GCC C++ Compiler->Preprocessor->Tool Settings
Don't forget to check Preprocessor Only(-E)
This worked for me on windows mingw32.