First Program. Compiles (sort of) then ".. Undefined reference to 'Winmain@16'

This is my first program.
Written on Notepad++
Compiled from command prompt using MinGW.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <math.h>
using namespace std ;

// define functions //

float calcBearing (float, float)  ;// declare calcBearing function
float calcDistance (float, float)  ;// declare calcDistance function
float checkBearing (float)  ;// declare checkBearing function
float calcBearing (float) ; // declare function for dNorth = 0


// declare global  variables

	float stnEast , stnNorth , tgtEast , tgtNorth , dEast , dNorth , dist , bearing ;
	const double PI = 3.1415926536 ;
	
int Main ()
	{
	// Get User input for the Four Variables //
	
	cout << "Enter Station Easting: \t" ;
	cin >> stnEast ;
	
	cout << endl << "Enter Station Northing: \t" ;
	cin >> stnNorth ;
	
	cout << endl << "Enter Target Easting: \t" ;
	cin >> tgtEast ;
	
	cout << endl << "Enter Target Northing: \t" ;
	cin >> tgtNorth ;
	
	
	
	dEast = ( tgtEast - stnEast ) ;
	dNorth = (tgtNorth - stnNorth ) ;
	
	// Call the functions
	
	(dNorth == 0) ? calcBearing (dEast) : calcBearing (dEast , dNorth) ;
	
	checkBearing (bearing) ;
	
	calcDistance (dEast , dNorth );
	
	// Send out results
	
	cout <<  "Bearing = " << bearing << endl ;
	cout <<  "Distance = " << dist << endl ;
	
	return 0 ;
	}
	
	// FUNCTIONS //
	
	float calcDistance ( float dEast , float dNorth )
		{
		dist = (sqrt ((dEast * dEast) + (dNorth * dNorth ))) ;
		return dist ;
		}
	
	float calcBearing (float dEast )
		{
		(dEast > 0)  ? bearing = 90 : bearing = 270 ;
		return bearing ;
		}
		
	float calcBearing (float dEast , float dNorth )
		{
		if (dNorth < 0 ) { bearing = ( (atan ( dEast / dNorth ) + 180 ) * (PI / 180) ) ; } 
		if (dNorth > 0 ) { bearing = ( (atan ( dEast / dNorth ) ) * ( PI / 180 ) )  ; } 
		return bearing ;
		}
	
	float checkBearing ( float bearing ) 
		{
		if ( bearing < 0 ) { bearing = bearing + 360 ; } 
		return bearing ;
		}


Now, please, at this stage try to refrain from pulling the code itself to pieces, as I know that it almost certainly clunky and inexpertly written. I have been teaching myself over the last few weeks and this is a first attempt at a 'proper' program

I have worked through compiling the code, and debugging it until I finally get the expected "... This should work unless it involves constant data structures referencing symbols from auto-imported DLLs." I say expected, as this has been the closing line when compiling all the examples that i have tried.

However, I then get;
c:/mingw/bin/../lib/gcc/mingw32/4.5.0/../../../libmingw32.a(main.o):main.c(.text+0xd2): undefined reference to `WinMain@16'
collect2: ld returned 1 exit status

I have tried googling references to winmain@16 both here and the wider web, and turned up articles on Linker errors.

My question, therefore, is;

Is this what is going on? Is the answer in the Linker Errors? I have not come across these and do not (yet) understand the articles that I have seen.
Or is there something else in the code that I am missing?

Once I have an idea of where to look for the answer to that niggle, I would very much appreciate any advice on improving the code itself.

Many Thanks

int main
Cheers Bazzy.
Now I do feel Stupid.
Feel free to pull the code to bits for me now.
You don't need braces after if if there's only one statement following
ie:
if ( x ) { y; } is equivalent to if ( x ) y;
But that's also a matter of taste

What you should do is avoid all those global variables, you don't need them and they make your functions non-reentrant
eg
57
58
59
60
61
	float calcDistance ( float dEast , float dNorth )
		{
		dist = (sqrt ((dEast * dEast) + (dNorth * dNorth ))) ;
		return dist ;
		}

should be
57
58
59
60
61
	float calcDistance ( float dEast , float dNorth )
		{

		return sqrt ((dEast * dEast) + (dNorth * dNorth )) ;
		}


and then at the call point:
dist = calcDistance (dEast , dNorth );
or
cout << "Distance = " << calcDistance (dEast , dNorth ) << endl;

And all those globals could well be local to main.

One other thing to notice about your global is that in checkBearing the parameter bearing shadows the global with the same name
Many thanks for the advice Bazzy.

I was getting Compile Errors on the IF statements which, went away when I added the Braces. Will look closer at this and whether it was actually something else in the original code.

Again, I found a similar problem when I had the variables local to main(). Changing them to Global fixed errors in the compiling.

I can see the benefit of loosing the 'dist' variable from Global in the manner that you have described.

My head is struggling at the moment with the differences of when to use Local or Global variables, I have to admit. Will keep researching and practicing to sort that out.

I would appreciate if you could explain your final statement about the parameter bearing shadowing the global of the same name. My thoughts on how the function's purpose were;
The function calcBearing returns possible negative values from -180 ~ +180
The desired program output is a value from 0 ~ 360
Therefor checkBearing looks at the value of bearing and if < 0 adds 360 to it's value.

Are you saying that it would be preferable to use an alternative name for the parameter, from the global?


Again. Many Thanks for your advice.
Here is a simplified version of the problem:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
float bearing;

float checkBearing ( float bearing )
    {
    if ( bearing < 0 ) { bearing = bearing + 360 ; } 
    return bearing ;
    }

int main()
{
    bearing = -5;
    checkBearing ( bearing );
    // bearing is still -5
}

Here is the above code with the global bearing called bearing_g and the parameter one called bearing_p:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
float bearing_g;

float checkBearing ( float bearing_p )
    {
    if ( bearing_p < 0 ) { bearing_p = bearing_p + 360 ; } // notice how this is changing the value of bearing_p
    return bearing_p ;
    }

int main()
{
    bearing_g = -5;
    checkBearing ( bearing_g );
    // bearing_g is still -5
}

In general, a variable declared in a smaller scope is the one that is visible in that scope
eg:
1
2
3
4
5
6
7
8
9
int x = 1;
int y = 2;
int z = 0;
{ // the code enclosed in two braces has a smaller scope than the code outside
    int x = 3;
    z = x + y; // the only z and y present in the program are those from the larger scope but
               // there are two x, the one with the smaller scope (the last declared) is the visible one
}
// z now is = 3 + 2 = 5  


If you get rid of the global variable you can solve the problem as follows:
1
2
3
4
5
6
7
8
9
10
11
12
float checkBearing ( float bearing )
    {
    if ( bearing < 0 ) { bearing = bearing + 360 ; } // this line still modifies only the parameter
    return bearing ; // this lines returns the modified value
    }

int main()
{
    float bearing = -5;
    bearing = checkBearing ( bearing ); // you call checkBearing and assign the returned value to the local variable
    // bearing is now 355
}


Another way to solve this problem is using references (see last link below) :
1
2
3
4
5
6
7
8
9
10
11
12
float checkBearing ( float& bearing ) // notice the & in the declaration, it will make the parameter "be" the passed variable
    {
    if ( bearing < 0 ) { bearing = bearing + 360 ; } // this line modifies the parameter ( and so the passed variable )
    return bearing ; // this lines returns the modified value
    }

int main()
{
    float bearing = -5;
    checkBearing ( bearing ); // the call to checkBearing modifies the local variable
    // bearing is now 355
}


See these tutorials for more detailed explanations:
http://www.cplusplus.com/doc/tutorial/variables/
http://www.cplusplus.com/doc/tutorial/functions/
http://www.cplusplus.com/doc/tutorial/functions2/
Thanks for the time spent explaining this Bazzy.
References appears to be the way to go (at my level) for now. Not something I had covered.

Will re-write and get working properly.

Thanks again
Topic archived. No new replies allowed.