Why does this code give an 'expression syntax' error? - c++

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

Related

auto type defaults to int instead of long [duplicate]

This question already has answers here:
Why does auto a=1; compile in C?
(7 answers)
Closed 4 years ago.
I've run into the following example where the auto declaration defaults to int instead of long:
#include <stdio.h>
int main(int argc, char **argv)
{
auto i = 999999999999999;
// long i = 999999999999999;
printf("i = %ld\n",i);
return 0;
}
When I compile this code, gcc indeed gives a relevant warning that i is actually an int:
$ gcc -o main main.c
main.c: In function ‘main’:
main.c:4:10: warning: type defaults to ‘int’ in declaration of ‘i’ [-Wimplicit-int]
auto i = 999999999999999;
^
main.c:4:14: warning: overflow in implicit constant conversion [-Woverflow]
auto i = 999999999999999;
^~~~~~~~~~~~~~~
main.c:6:19: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘int’ [-Wformat=]
printf("i = %ld\n",i);
~~^
%d
But I'm wondering why gcc's lexical scanner didn't label 999999999999999 as being long when it has all the information to do so? Here is the output of the program:
$ ./main
i = 2764472319
EDIT:
Here is the output of the correct answer (from #Yang) with g++:
$ g++ -o main main.c
$ ./main
i = 999999999999999
And another option for doing it:
$ cp main.c main.cpp
$ gcc -std=c++11 -o main main.cpp
$ ./main
i = 999999999999999
If you want type inference, auto is a C++ feature. Could you try compiling with g++ instead?
In C and C++98/C++03, auto is a redundant keyword meaning "automatic variable." So in your example, i is a variable with no explicit type which is therefore treated as an int (but C99 and later requires a diagnostic).

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.

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

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];
^

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];
^

C++ I'm expecting a narrowing conversion error but not getting it

In the following code from Stroustrup's book we are warned against an error from a narrowing conversion which does not occur on my version GCC (4.7.2)
#include <iostream>
using namespace std;
int main()
{
int i1 = 7.2;
int i2{7.2};
cout << i1 << " " << i2 << endl;
return 0;
}
As demonstrated here at ideone is this a bug or am I not running with the appropriate command line arguments to the compiler? Or is this meant to be a purely semantic error?
With g++ 4.8.1:
foo.cpp: In function 'int main()':
foo.cpp:8:15: warning: narrowing conversion of '7.2000000000000002e+0' from 'double' to 'int' inside { } [-Wnarrowing]
int i2{7.2};
^
I assume it's simply a bug in 4.7.2's c++11 support.
I get a narrowing warning with GCC 4.7.3 when I use -std=c++0x:
g++ -std=c++0x test.cpp
test.cpp: In function ‘int main()’:
test.cpp:8:23: warning: narrowing conversion of ‘7.2000000000000002e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
g++ --version
g++ (GCC) 4.7.3