Multi-dimensional array of unknown bounds argument : difference between C and C++ - c++

The following program compiles as a C program:
#include <stdlib.h>
#include <stdio.h>
void f(int n, int m, int x[n][m]) {
printf("x[0][2] = %i\n",x[0][2]);
}
int main() {
int v[][3] = { {0,1,2}, {3,4,5} };
f(2,3,v);
}
However, when compiled as C++ with g++, I have:
main.c:4:29: error: use of parameter outside function body before ‘]’ token
void f(int n, int m, int x[n][m]) {
^
It seems that this feature of C does not exist in C++. Is there any flag that can be given to g++ so that it accepts the code?

It seems that this feature of C does not exist in C++.
Correct.
Is there any flag that can be given to g++ so that it accepts the code?
No, there is no such feature allowing a VLA as part of a parameter list. You will have to compile the code as C.
Other similar gcc extensions exist, see: https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

Related

Where is the syntax with class as a parameter in main needed?

This question states that main can be implementation defined with some restrictions.
So, I wrote the following C++ code to try out the following signature of main:
main.h
class MyClass {
private:
int i;
public:
MyClass();
inline int geti() {
return i;
}
inline void seti(int i) {
this->i = i;
}
~MyClass();
};
MyClass::MyClass() {
this->i = 2;
}
MyClass::~MyClass() {
}
main.c++
#include <iostream>
#include "main.h"
int main(MyClass myClass) {
std::cout << myClass.geti() << std::endl;
return 0;
}
Which Gives the following results:
The command g++ -o main main.c++ -O3 compiles successfully with warnings:
main.c++:5:5: warning: first argument of ‘int main(MyClass)’ should be ‘int’ [-Wmain]
5 | int main(MyClass myClass) {
| ^~~~
main.c++:5:5: warning: ‘int main(MyClass)’ takes only zero or two arguments [-Wmain]
The command clang++ -o main main.c++ -std=c++14 gives the error:
main.c++:5:5: error: first parameter of 'main' (argument count) must be of type 'int'
int main(MyClass myClass) {
^
1 error generated.
the main file generated by g++ gives SIGSEGV (why though?)
So, if main can be implementation defined, why does clang give an error while g++ generated file give SIGSEGV?
I also went further and created a different code so that I will be able to pass a MyClass object to main.c++ as follows:
#include <iostream>
#include "main.h"
#include <unistd.h>
int main() {
MyClass myClass;
execve("./main",myClass,NULL);
return 0;
}
However, as execve takes the second parameter to be a char* const *, it does not compile. How do I pass the myClass object to the main file generated by g++?
The command g++ -o main main.c++ -O3 compiles successfully with warnings
This is not successful compilation. You should always use -Werror. If you fail to do so and then decide to ignore the warning and proceed with running the program, it's your own responsibility. You better know full well what you are doing. See this for more information.
the main file generated by g++ gives SIGSEGV (why though?)
The compiler has warned you. It is in your best interest to listen to it. If things go boom, chances are, that's because you have ignored warnings.
why does clang give an error while g++ generated file give SIGSEGV?
The program is not a valid C++ program. There is no meaningful difference between a warning and an error.
How do I pass the myClass object to the main file generated by g++?
You cannot. main must have a form equivalent to one of these two:
int main()
int main(int argc, char* argv[])
(Optional reading in italics) Other forms of main are implementation-defined. This means your implementation needs to support them in a documented way. Unless you have read documentation for your implementation and found that it supports the form of main you want, there's no way to do that.
Other than having an implementation-defined main, the only way a program can get hold of an object of a class type is by constructing that object.
You are close. You have identified your primary issue attempting to pass as a parameter to main() -- that won't work. The declaration for main() is defined by the standard and you are limited to passing string values (nul-terminated character arrays... C-Strings) in as arguments.
In your case you need to create an instance of your class within main(), e.g.
#include <iostream>
#include "main.h"
int main() {
MyClass myClass;
std::cout << myClass.geti() << std::endl;
return 0;
}
Your main.h header has a variable shadowing problem where at line 10:
inline void seti(int i) {
int i shadows a prior declaration at line 3, e.g. int i; (though the consequence would be unlikely to matter). Just replace the variable name in the second declaration with j (or whatever you like). Your code will compile without warning, e.g.
class MyClass {
private:
int i;
public:
MyClass();
inline int geti() {
return i;
}
inline void seti(int j) {
this->i = j;
}
~MyClass();
};
MyClass::MyClass() {
this->i = 2;
}
MyClass::~MyClass() {
}
Example Use/Output
$ ./bin/main
2
You can also call your seti() function to update the private variable in your class, e.g.
myClass.seti(5);
std::cout << myClass.geti() << std::endl;
Which would now output 5.
Let me know if you have further questions.

error: expected unqualified-id before string constant extern "a" {

So, this problem, for some reason it shows me this error (ubuntu, terminal, g++). I searched the net and didn't show anything similar to mine. The code is (gfdz.cpp)
#include <iostream>
#include <string>
using namespace std;
struct dynmass
{
unsigned long int vm; //вместимость
unsigned long int el; //количество элементов
};
int *i,*q;
void create()
{
dynmass a;
a.vm = 0;
a.el = 0;
i = new int[0];
extern "a"
{
void push();
void remuve();
int kolichestvo();
int vmestimostb();
int main;
};
}
What you have there is a language linkage specification. And within it, you have a bunch of function declarations.
A language specifications can only appear in namespace scope. Yours is in the block scope, so that's what's wrong with it. Also, "a" language linkage is not supported by standard c++ so you may need to consult your compiler manual to find out if it's supported.

Compiling C program in C++ compiler

I wrote a program in C and I want to use C++ library in this code, I though that I will be able to compile the C in g++ since C++ built in top of C. However, I couldn't do that and the main error was because in one part of the code I wrote a function to read data from input file, before the main function. That worked well in C compiler but not in Cpp compiler.
Below is some of the error messages I got, so I'd like to get general comments and points to take into consideration when use c and cpp interchangeably
error : ‘get_inputs’ was not declared in this scope
error: use of parameter outside function body before ‘]’ token
Following program compiles in C with a warning such as: 'bar' undefined; assuming extern returning int
void foo()
{
bar(5);
}
int bar(int x)
{
return x*2;
}
If you want this to compile in C++ you must declare bar before you use it:
int bar(int x); // forward declaration
void foo()
{
bar(5);
}
int bar(int x)
{
return x*2;
}
Even in C it's good practice to use forward declarations and to enable all compiler warnings otherwise the error in following program will slip through:
void foo()
{
bar(); // calling bar without argument....
}
int bar(int x)
{
return x*2; // ... will result in an undefined value for x here
}

C++ name mangling in C

C language does not use name mangling like C++. This can lead to subtle bugs, when function prototype is declared differently in different files. Simple example:
/* file1.c */
int test(int x, int y)
{
return y;
}
/* file2.c */
#include <stdio.h>
extern int test(int x);
int main()
{
int n = test(2);
printf("n = %d\n", n);
return 0;
}
When compiling such code using C compiler (in my case gcc) no errors are reported. After switching to C++ compiler, linking will fail with error "undefined reference to 'test(int)'". Unfortunately in practice this is not so easy - there are cases when code is accepted by C compiler (with possible warning messages), but compilation fails when using C++ compiler.
This is of course bad coding practice - all function prototypes should be added to .h file, which is then included in files where function is implemented or used. Unfortunately in my app there are many cases like this, and fixing all of them is not possible in short term. Switching to g++ is also not at option, I got compilation error quite fast.
One of possible solutions would be to use C++ name mangling when compiling C code. Unfortunately gcc does not allow to do this - I did not found command line option to do this. Do you know if it is possible to do this (maybe use other compiler?). I also wonder if some static analysis tools are able to catch this.
Using splint catches these kinds of errors.
foo.c:
int test(int x);
int main() {
test(0);
}
bar.c:
int test(int x, int y) {
return y;
}
Running splint:
$ splint -weak foo.c bar.c
Splint 3.1.2 --- 20 Feb 2009
bar.c:1:5: Function test redeclared with 2 args, previously declared with 1
Types are incompatible. (Use -type to inhibit warning)
foo.c:4:5: Previous declaration of test
Finished checking --- 1 code warning
~/dev/temp$ cat > a.c
int f(int x, int y) { return x + y; }
~/dev/temp$ cat > b.c
extern int f(int x); int g(int x) { return f(x + x); }
~/dev/temp$ splint *.c
Splint 3.1.2 --- 03 May 2009
b.c:1:12: Function f redeclared with 1 arg, previously declared with 2
Types are incompatible. (Use -type to inhibit warning)
a.c:1:5: Previous declaration of f
Finished checking --- 1 code warning
~/dev/temp$

C++ - struct errors

Following an example at: http://www.learncpp.com/cpp-tutorial/47-structs/ relating to structs, and when I tried to compile this program:
#include <iostream>
void PrintInformation(Employee sEmployee)
{
std::cout<<"ID: "<<sEmployee.nID<<std::endl;
std::cout<<"Age: "<<sEmployee.nAge<<std::endl;
std::cout<<"Wage: "<<sEmployee.fWage<<std::endl;
}
struct Employee {int nID;int nAge;float fWage;};
int main()
{
Employee abc;
abc.nID=123;
abc.nAge=27;
abc.fWage=400;
// print abc's information
PrintInformation(abc);
return 0;
}
I get the following:
Why is that?
Thanks.
You need to declare the struct before the function that attempts to use it.
C (and by extension, C++) were designed for "single-pass" compilation. Therefore, everything must be available to the compiler by the time it's required.