C++ initialize array size using constant variable [duplicate] - c++

int a;
cin >> a;
int ints[a];
Why does this not throw any kind of warning while compiling? How do I know when this array thing is actually using the heap or the stack?
g++ -std=c++11 -Wall *.cpp -o main

ISO C++ disallows the use of variable length arrays, which g++ happily tells you if you increase the strictness of it by passing it the -pedantic flag.
Using -pedantic will issue a warning about things breaking the standard. If you want g++ to issue an error and with this refuse compilation because of such things; use -pedantic-errors.
g++ -Wall -pedantic -std=c++11 apa.cpp
apa.cpp: In function ‘int main(int, char**)’:
apa.cpp:8:13: warning: ISO C++ forbids variable length array ‘ints’ [-Wvla]
int ints[a];
^
apa.cpp:8:7: warning: unused variable ‘ints’ [-Wunused-variable]
int ints[a];
^

Related

g++ compile options with -std=c++14 compile error showing Werror=c++11-compat

My environment Arch Linux, gcc 7.2
I'm learning C++ and I'm using keyword constexpr to define a constant, while compile, it give me an error message
error: identifier ‘constexpr’ is a keyword in C++11 [-Werror=c++11-compat]
I can compile my program with default g++, but cannot compile with -std=c++14 and -Werror
The command I'm using is:
g++ -std=c++14 -O2 -Wall -Werror -Wextra -ansi -flto
I believe the -Werror option caused the issue. but what is the issue? can someone tell me please?
#include <iostream>
int main() {
constexpr double yen_dollar = 0.107;
std::cout << yen_dollar << std::endl;
return 0;
}
test.cpp:4:5: error: identifier ‘constexpr’ is a keyword in C++11 [-Werror=c++11-compat]
constexpr double yen_dollar = 0.107;
^~~~~~~~~
test.cpp: In function ‘int main()’:
test.cpp:4:5: error: ‘constexpr’ was not declared in this scope
test.cpp:5:16: error: ‘yen_dollar’ was not declared in this scope
std::cout << yen_dollar << std::endl;
From the GCC documentation §3.4 Options Controlling C Dialect, one can read:
-ansi
In C mode, this is equivalent to -std=c90. In C++ mode, it is equivalent to -std=c++98.
Since, you compiled with
g++ -std=c++14 -O2 -Wall -Werror -Wextra -ansi -flto
-ansi overwrites -std=c++14 with -std=c++98. This is why constexpr is not recognized.
Solution: get rid of the -ansi flag.

g++ variable size array no warning?

int a;
cin >> a;
int ints[a];
Why does this not throw any kind of warning while compiling? How do I know when this array thing is actually using the heap or the stack?
g++ -std=c++11 -Wall *.cpp -o main
ISO C++ disallows the use of variable length arrays, which g++ happily tells you if you increase the strictness of it by passing it the -pedantic flag.
Using -pedantic will issue a warning about things breaking the standard. If you want g++ to issue an error and with this refuse compilation because of such things; use -pedantic-errors.
g++ -Wall -pedantic -std=c++11 apa.cpp
apa.cpp: In function ‘int main(int, char**)’:
apa.cpp:8:13: warning: ISO C++ forbids variable length array ‘ints’ [-Wvla]
int ints[a];
^
apa.cpp:8:7: warning: unused variable ‘ints’ [-Wunused-variable]
int ints[a];
^

Why does this code give an 'expression syntax' error?

Why do I get the error
Expression Syntax
on the m[0]= line in the code below?
struct menu{
int code;
char name[30];
}m[5];
int main() {
clrscr();
m[0]={1,"MAGGI"}; //try to check whether this works or not and it didn't actually
<<endl;
cout<<m[0].code<<"\t"<<m[0].name;
getch();
return 0;
}
Succinctly — you can't do that in C++ with the struct menu as written with just default constructors.
In C99, you could use:
m[0] = (struct menu){ 1, "MAGGI" }; // C99 compound literal
Even in C++11, that (meaning 'using a compound literal') is not valid.
The unadorned use of endl; attempts to generate a function pointer, but the function is overloaded so it doesn't compile. You should add an << endl to the end of the output, though.
G++ allows C99-style compound literals
It is interesting that GCC (tested GCC 4.7.1 on Mac OS X 10.8.4) accepts the compound literal notation, even with stringent warnings, but this is a GCC/G++ extension over standard C++:
g++ -O3 -g -Wall -Wextra -c x91.cpp
Code:
#include <iostream>
using namespace std;
struct menu
{
int code;
char name[30];
} m[5];
int main()
{
m[0] = (struct menu){ 1, "MAGGI" };
cout << m[0].code << "\t" << m[0].name << endl;
return 0;
}
You have to provoke G++ fairly hard to get it to complain:
$ g++ -O3 -g -Wall -Wextra -std=c++98 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:11:34: warning: ISO C++ forbids compound-literals [-pedantic]
$ g++ -O3 -g -Wall -Wextra -std=c++11 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:11:34: warning: ISO C++ forbids compound-literals [-pedantic]
$
C++ 2011 and 'list initialization' or 'extended initializer lists'
I think section 8.5 Initializers in general and 8.5.4 List-initialization in particular mean that you can in fact write what you originally had, if your class (structure in the example) has the appropriate support.
Consider this minor variant on your original code:
#include <iostream>
#include <cstring>
using namespace std;
struct menu
{
int code;
char name[30];
menu(int c, const char *n) : code(c) { strncpy(name, n, sizeof(name)); name[sizeof(name)-1] = '\0'; }
menu() : code(0) { name[0] = '\0'; }
} m[5];
int main()
{
menu m0 = { 2, "MAGGI 2" };
m[0] = (struct menu){ 1, "MAGGI 1" };
m[1] = { 3, "MAGGI 3" };
cout << m[0].code << "\t" << m[0].name << endl;
cout << m0.code << "\t" << m0.name << endl;
cout << m[1].code << "\t" << m[1].name << endl;
return 0;
}
This code compiles OK under G++, subject to warnings about compound literals not being part of standard C++, when compiled as shown:
$ g++ -O3 -g -Wall -Wextra -std=c++11 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:16:39: warning: ISO C++ forbids compound-literals [-pedantic]
$ ./x91
1 MAGGI 1
2 MAGGI 2
3 MAGGI 3
$
We can debate the wisdom of the use of strncpy() — that is tangential to the subject under discussion. The default constructor is needed to allow the array to be defined. The other constructor is necessary for the extended list initialization. Comment out the non-default constructor and you get scads of compilation messages:
$ g++ -O3 -g -Wall -Wextra -std=c++11 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:15:29: error: could not convert ‘{2, "MAGGI 2"}’ from ‘<brace-enclosed initializer list>’ to ‘menu’
x91.cpp:16:39: warning: ISO C++ forbids compound-literals [-pedantic]
x91.cpp:16:39: error: no matching function for call to ‘menu::menu(<brace-enclosed initializer list>)’
x91.cpp:16:39: note: candidates are:
x91.cpp:10:5: note: menu::menu()
x91.cpp:10:5: note: candidate expects 0 arguments, 2 provided
x91.cpp:5:8: note: constexpr menu::menu(const menu&)
x91.cpp:5:8: note: candidate expects 1 argument, 2 provided
x91.cpp:5:8: note: constexpr menu::menu(menu&&)
x91.cpp:5:8: note: candidate expects 1 argument, 2 provided
x91.cpp:17:26: error: no match for ‘operator=’ in ‘m[1] = {3, "MAGGI 3"}’
x91.cpp:17:26: note: candidates are:
x91.cpp:5:8: note: menu& menu::operator=(const menu&)
x91.cpp:5:8: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const menu&’
x91.cpp:5:8: note: menu& menu::operator=(menu&&)
x91.cpp:5:8: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘menu&&’
$
In C++98 mode (with both constructors present), you get a warning about using 'extended initializer lists' outside C++11 compliance mode:
$ g++ -O3 -g -Wall -Wextra -std=c++98 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:15:29: error: in C++98 ‘m0’ must be initialized by constructor, not by ‘{...}’
x91.cpp:16:39: warning: ISO C++ forbids compound-literals [-pedantic]
x91.cpp:17:26: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]
$
Declare constructors for the struct and use them. Also try using std::string over char[]. It is not possible to do as you have done. the constructor could be as
menu(int _code, string _name):code(_code), name(_name)
{} //changing name to string
with that, don't forget to declare a default constructor as well as you are creating an array of struct variables

Forcing GCC 4.x to treat -Wreturn-type as an error without enabling -Werror?

Suppose we have the following code:
#if !defined(__cplusplus)
# error This file should be compiled as C++
#endif
#include <stdio.h>
#include <string>
//#define USE_CXX_CLASS
#ifdef USE_CXX_CLASS
class SomeClass
{
public:
SomeClass() {}
~SomeClass() {}
std::string GetSomeString()
{
// case #1
}
};
#endif // USE_CXX_CLASS
int foo()
{
// case #2
}
int
main (int argc, char *argv[])
{
(void)argc;
(void)argv;
#ifdef USE_CXX_CLASS
SomeClass someInstance;
someInstance.GetSomeString();
#endif // USE_CXX_CLASS
foo();
return 0;
}
And suppose that it were to be compiled the C++ compiler (and not the C compiler) from GCC version 4.2.1 with the options -Wreturn-type -Werror=return-type. If the above code is compiled as is without first uncommenting the //#define USE_CXX_CLASS line above, then you will see a warning but no error:
.../gcc-4.2.1/bin/g++ -g -fPIC -Wreturn-type -Werror=return-type test.cpp -c -o test.o
test.cpp: In function 'int foo()':
test.cpp:26: warning: control reaches end of non-void function
But if the //#define USE_CXX_CLASS line is uncommented, then the warning is treated as an error:
.../gcc-4.2.1/bin/g++ -g -fPIC -Wreturn-type -Werror=return-type test.cpp -c -o test.o
test.cpp: In member function 'std::string SomeClass::GetSomeString()':
test.cpp:18: error: no return statement in function returning non-void [-Wreturn-type]
gmake: *** [test.o] Error 1
Yes, one is a non-member function (case #2), and the other is a C++ function (case #1). IMO, that should not matter. I want both conditions treated as an error, and I don't want to add -Werror or -Wall at this point in time (probably will do so later, but that is out of scope of this question).
My sub-questions are:
Is there some GCC switch that I am missing that should work? (No I do not want to use #pragma's.)
Is this a bug that has been addressed in a more recent version of GCC?
For reference, I have already poured through other similar questions already, including the following:
Why does flowing off the end of a non-void function without returning a value not produce a compiler error?
C question: no warning?
Is a return statement mandatory for C++ functions that do not return void?
It has been fixed, it works well with g++ 9.3: both member functions and free functions are treated as error with -Wall -Werror=return-type
I do see an error even w/o the USE_CXX_CLASS flag. i.e. g++ is consistent with the error for both class member functions and non member functions.
g++ (GCC) 4.4.3 20100127 (Red Hat 4.4.3-4)
It seems to me that what you need is a shell script wrapper around gcc.
Name it something like gcc-wrapper and g++-wrapper.
In your Makefile set CC and CXX to the wrappers.
Have the wrapper invoke GCC and pipe its output to another program which will search for your desired warning strings.
Have the search program exit with an error when it finds the warning.

Using size of one array in another array

// sizeofarray.cpp
#include <iostream>
template <typename T,int N>
int size(T (&Array)[N])
{
return N;
}
int main()
{
char p[]="Je suis trop bon, et vous?";
char q[size(p)]; // (A)
return 0;
}
I heard that an array size in C++ must be a constant expression. So char q[size(p)] is invalid, am I right? But I got no errors when I tried
g++ -Wall sizeofarray.cpp
Why?
Like Prasoon says, it's not a constant expression. For now, you can get a constant-expression value of the size of an array like this:
template <std::size_t N>
struct type_of_size
{
typedef char type[N];
};
template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);
#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))
Explanation here. You basically encode the size of the array into the size of a type, then get the sizeof of that type, giving you:
char q[sizeof_array(p)];
I heard that an array size in C++ must be a constant expression.
Correct
So char q[size(p)] is invalid, am I right?
According to ISO C++, yes!
But I got no errors when I tried
g++ -Wall sizeofarray.cpp
That's because g++ supports VLA (Variable Length Array) as an extension.
In C++0x there is constexpr feature with the help of which you can write
constexpr int size(T (&Array)[N])
{
return N;
}
and then char q[size(p)] would be legal.
EDIT : Also read this article [blog whatever]
I beg to differ with all the answers here. The code show is perfectly fine except for a minor issue (which is definitely not VLA)
template <typename T,int N>
int size(T (&Array)[N])
{
return N;
}
int main()
{
char p[]="Je suis trop bon, et vous?";
char q[sizeof(p)]; // (A), not sizeof and not size as in OP
return 0;
}
I was wondering that the result of the sizeof is always a const value, and hence the code should be fine.
The above code builds fine on VS 2010 and Comeau(strict mode)
$5.3.3/6- "The result is a constant of
type size_t. [Note: size_t is defined
in the standard header (18.1)."
I use g++ 4.4.3 and have the following alias so that I never forget to turn on the warnings:
$ alias g++
alias g++='g++ -ansi -pedantic -Wall -W -Wconversion -Wshadow -Wcast-qual -Wwrite-strings'
If compiled with the above, there would be some warnings. Following steps show how different options show different warnings.
Compilation with no warning option does not show any warning
$ \g++ sizeofarray.cpp
Turning on -Wall
$ \g++ -Wall sizeofarray.cpp
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: unused variable ‘q’
Turning on -Wextra
$ \g++ -Wall -Wextra sizeofarray.cpp
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: unused variable ‘q’
sizeofarray.cpp: At global scope:
sizeofarray.cpp: In instantiation of ‘int size(T (&)[N]) [with T = char, int N = 27]’:
sizeofarray.cpp:12: instantiated from here
sizeofarray.cpp:4: warning: unused parameter ‘Array’
Finally turning on -pedantic to catch the real problem
$ \g++ -Wall -Wextra -pedantic sizeofarray.cpp
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: ISO C++ forbids variable length array ‘q’
sizeofarray.cpp:12: warning: unused variable ‘q’
sizeofarray.cpp: At global scope:
sizeofarray.cpp: In instantiation of ‘int size(T (&)[N]) [with T = char, int N = 27]’:
sizeofarray.cpp:12: instantiated from here
sizeofarray.cpp:4: warning: unused parameter ‘Array’