简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM