Basics of C++ Language




Summary

The basics of C language
          Types of Variables
          Initialized and constant variables
          The Functions: a group of instructions
          Function: How to define a new function
          Functions: how to declare the type of input parameters
          Functions: how to define the type of returned value
                    Returning a pointer
          Function: the missing of input parameters or returned value
          The Structures
          The "union" used in structure declarations
          Unions and different Types
          Other examples about declaration of variables
          The pointers: examining in depth
          The relationship between pointers and vectors
          A pointer to access to vectors
          Pointers to access to structures
          The pointer of another pointer
          How to convert the types of variables
          The cast-type with the (CASTING) operator
          Main C statements (instructions)
          The "if" statement
          The switch() case statements
          The "break" instruction in the switch statement
          The "default" istruction in the switch statement
          The for() statement
          The "break" instruction in the for statement
          The while() statement
Common error messages from C++ Compiler
          Error: 'x': undeclared identifier
                    Solution
          Another reason of "undeclared identifier" error
                    Solution
          Error 'x' : redefinition; different type modifiers
                    Solution.
          Error C4706: assignment within conditional expression
                    Solution
          Error C2440: '=' :cannot convert from 'xxx' to 'yyyy' or "C2446: '==' : no conversion from 'xxx' to 'yyy'
                    Solution
          Example of: "no conversion from 'xxx' to 'yyy'" error
                    Solution
          Another example of error: "no conversion from 'xxx' to 'yyy'"
                    Solution
          Errors about indirections and pointer arguments: "error C2100: illegal indirection"
          local function definitions are illegal
                    Solution
          Error C2143: syntax error : missing 'x' before 'y'
                    Solution
          Warning C4715: 'FunctionName' : not all control paths return a value
                    Solution
          Warning C4101: 'VariableName' : unreferenced local variable
          The auto member list skill stopped working
                    Solution
          Error LNK1207: incompatible PDB format
                    Solution







The basics of C language

Since I've not the ambition to write a manual about programming in C++, because it should be too long and futile since there are already a lot of references about C++ on internet, in this chapter I'll explain only the basics to type little C functions.
In a C function we'll begin declaring our variables, then we can perform computations in a way that is almost the same in algebrical notation with only little exceptions


int MyFunction(int Alfa, int beta)
{
          int Result;

          Result = Alfa * Beta;

          Result = Result + 2;

          Result = Result / 23;

          return Result;
}


Types of Variables

The statement to declare a variable in C++ is very easy.
In first position there will be the TYPE of variable, followed by the name we assigned to this variable.
If we wish having many of these variables in a contiguous zone (a vector or array) just placing at right a couple o squared parenthesis with inside the number of items we wish.
At end of each C++ declaration we'll type a semicolon ";" character to complete the line.
In spite there were very much types in C, we'll use always one of following few types:

char

Examples:

char LittleNumber;
char MexType[] = "Game Over";

char should be a signed byte, where you can store numbers in the range: -128 +127
However the char is more often used to declare strings of text.

BYTE

Examples:

BYTE MyLittleNumber;
BYTE VetPickedSecrets[99];

The BYTE type is for unsigned numbers in the range 0 +255

short

Examples:

short NumberOfDarts;
short VectLevels[50];

Short is a 16 bits signed number, it can hosting values in the range -32536 +32535

WORD

Examples:

WORD NMediPacks;
WORD MyTable[30*16];

WORD is a 16 bits unsigned number, it can hosting values in the range 0 +65535

int or long

Examples:

int LastYLara;
long ElapsedTime;

The types int and long are synonymous, at least in "our" 32 bits flat assembly that we'll use.
They are 32 bits signed numbers, they can hosting values in the range: -2,147,483,648 +2,147,483,647

DWORD

Examples:

DWORD LastTickFrames;
DWORD CordX;

The DWORD type is an unsigned 32 bits number, it can hosting values in the range 0 + 4,294,967,296

float

Examples:

float FogDistanceMin;
float FogDistanceMax;

While other types we saw were always integers values, with no hosting for digits after point, the float is a floating point value where we can host values with the point and many digits after the point. The range is approximately 3.4E-38 to 3.4E+38
Tomb4 engine uses integers DWORD or int values for coordinates of moveables and statics (X and Z are dwords, Y is long), anyway when tomb4 builds the 3d world those integer values will be converted in float values.
For this reason in some circustances we need to manage also float values.

Initialized and constant variables

When we declare a variable we can also initialize it with some values.
In the case we mean do not change evermore those values, we are using constant values, and it should be weird call them: "variables", anyway we can need them for some compute and in this case we can declare these values directly in the source, both by loading them from some binary file from disk. The choice depends by the quantity of these values, of course.

To initialize a single variable, just using a "=" character after the name of variable, followed by the value to assign to it.
Examples:

WORD MyVar= 54;
float FogDistance = 15.00;

More interesting is when we wish fill a multisize variable, like a vector or an array.
In this case we can type a list of values, divided by commas, for numbers, or store all characters in the quotes, for the text.
Examples:

char MexWarning[] = "Warning: this plugin might be not compatible with current tomb_nextgeneration.dll version. You should use 1.2.2.9 version";

WORD VetGrowingPower[]={1, 1, 1, 2, 2, 3, 3, 4, 5, 7, 9, 11, 15};

int Vettore[40]={2,2,2,4,5,6};

About above examples, we can see that in many circustances we'll not type any value in the squared parenthesis, where we should type the number of items.
The reason is because when you omit the dimension number (the value in squared parenthesis), the compiler will resize our vector to host all values you typed after the "=" character.
Since this solution is ideal in the most of cases, we very often will use this chance.
Anyway theorically we can also set the dimension of our vector and then to type also first values for it.

The Functions: a group of instructions

Since this tutorial has been thought for absolute beginners in programming, I'll try to explain that basic brick of programming that is a "function".
As general rule, a program is a sequence of istructions. Some instructions perform computations, like:

          a = b + 3;
          c = a * 40;

Others are conditions, to perform a test on some value inside a variable, and then, in according with result of the test, it will be executed a group of instructions or another.

          if (a > 3) {
                    b=0;
          }else {
                    b=1;
          }

In above example, the instruction: "b=0" it will be executed only when "a greather than 3".


Function: How to define a new function

A function is simply a group of instructions that we give a name.
The logic is: when we need more than once to perform a serie of instructions, from different side of our source, it's better typing that sequence only once, and then "call" it from different sides, rather duplicating, over and over, same instructions.
A function will have:
- A name
- Some input parameters
- A returned value
Really it's not always true above list, some function could have no input parameters and neither a returned value, anyway most cases they have them.

Let's we need in our program to have to compute different times the instructions to find the max value between three variabile: a, b and c.

Each variable is a box with inside a given value, that could change in the progress of the execution.
We can create a function to perform this computation.
It will have three parameters to receive the three variables to check.
And it will return a value, the greatest value of those three input variables.
This function could be like this:

int GetMaxValue(int a, int b, int c)
{
          if ( a > b && a > c) return a;
          if (b > a && b > c) return b;
          return c;
}

Above function yet doesn't make anything, of course. We have to call it, passing to it real values to see it was executed.
So we can call now above function in different sides of our source, and it's interesting see how we can call it also in different ways:
Below there are different way "to call" above function:

          MaxValue= GetMaxValue(CordY, FloorY, LaraY);

          if (GetMaxValue(z, ShotZ, 0) == 0) {
                    // perform some code ...

          }

From above code we can see two main way to use a function:
We can store the value it returned in some variable, like in the case of:

          MaxValue= GetMaxValue(CordY, FloorY, LaraY);

Or use immediately the returned value, in another computation or to compare it with another value, usign a testing instruction:

          Result =2 + GetMaxValue(x1,x2,x3) * 100;
          
          if (GetMaxValue(z, ShotZ, 0) == 0) {
                    // perform some code ...

          }

Another little discovery is that we have no need to use same variable names we set in original definition of that function.
Indeed, in spite our function had following input parameters:

int GetMaxValue(int a, int b, int c)

We called it, passing different variables or constant values.
When we called it in this way:

          MaxValue= GetMaxValue(CordY, FloorY, LaraY);

The final code, in above example, will perform following instructions:

          a = CordY;
          b = Floory;
          c = LaraY;
          // and then "call" the function, i.e. it will be performed following instructions:
          if ( a > b && a > c) return a;
          if (b > a && b > c) return b;
          return c;

Further explanation now is about that "return" instruction.
When a function use a "return" instruction, the value typed after the return, it will be "returned" to the calling code.
So if our calling code was:

          MaxValue= GetMaxValue(CordY, FloorY, LaraY);

And the function returns (a little variation from our original example) the value -482, in the MaxValue will be written the same value of operand of "return" instrucion, so it will become like:

          MaxValue = -482;

Really in our function we returned only variables, and in this case it will be value inside the returned variable to be written in MaxValue.
So, if the biggest value was that in "FloorY" in above example, and we suppose that in FloorY variable there was the "37" value.
It will happen these sequence of swapping:

          MaxValue= GetMaxValue(CordY, FloorY, LaraY);

          FloorY is second parameters, so it will be copied in second input parameter of GetMaxValue() function, that was "b" local (of that function) variable:

int GetMaxValue(int a, int b, int c)

Then, supposing that the value in second parameter (named "FloorY" variable in calling code, and "b" variable in function's code), it will be performed this final instruction:

          if (b > a && b > c) return b;

Since we supposed the second parameter (FloorY or b, are the biggest), the return used will be "return b"
The value inside "b" variable will be returned to calling code, and it will go inside of "MaxValue" variable:

          MaxValue= GetMaxValue(CordY, FloorY, LaraY);


Functions: how to declare the type of input parameters

Coming newly back to our function:

int GetMaxValue(int a, int b, int c)
{
          if ( a > b && a > c) return a;
          if (b > a && b > c) return b;
          return c;
}

We defined the input parameters in this way:

(int a, int b, int c)

We recognize same way to initialise a variable, like:

          int a;
          int b;
          int c;

Indeed, it is almost same operation.
Only difference is that we type the initialisation of parameters inside of round parenthesis and we separate them with commas, omitting the final semicolon ";" character.
Anyway the possible types are the same we already saw at top of this document.
In our example we declared "a", "b" and "c" as "int" type but we can use other types.
For instance, if we need to "pass" (i.e. give a value to the function, storing it in some of its input parameters) a string, we should declare that input parameter in this way:

void PrintText(char *Message)
{
          // code to print the string (text) received in input parameter named "Message"

}

And we could call above function in this way:

          PrintText("Hello World");
          // or also, supposing to have in our source a constant string like this:
char MyText[] = {"Hello World"};
          // we could call our funcion in this way:
          PrintText(MyText);


Functions: how to define the type of returned value

When we create a new function, the first thing to write is own the type of returned value.
Indeed, in our above function:

int GetMaxValue(int a, int b, int c)
{
          if ( a > b && a > c) return a;
          if (b > a && b > c) return b;
          return c;
}

That "int" at left of "GetMaxValue(" is own the type of returned variable. In this case it is an "int" type.
Also for returned value we can use all types we know.
The only difference is that we don't type a name for that variable, since it will be own the function's name to be used to access, once called that function, to read that value.
For this reason we can use a function name almost like it was a variable:

          if (GetMaxValue(alfa, beta, delta)== 4) {

          }
          // like we did
          if (MaxValue == 4) {

          }


Returning a pointer
Now, in this tutorial, we'll see better the pointers and structures topic, anyway now we can simply remember that also the functions can returning a pointer, of course, and it is enough common.
Since a pointer to some data it described always like:
[PointedType] *
I.e., a definition like:

int *
char *
StrItemTr4 *

Also defining a pointer as returned value, we'll use same syntax.
If we crate a function that has to return a string, we'll define it in this way:

char * GetString(int Index)
{

}


Function: the missing of input parameters or returned value

It's possible that a function had no input parameter, in this case we'll type inside of its round parenthesis the keyword "void"

int GetAmountOfItems(void)
{

}

By the way, it could happen also that was the returned value to be not present. Also in this case we'll replace the returned type with "void" keyword:

void DrawSprite(int x, int y, int SpriteIndex)
{

}



The Structures

A structure is a mix of different variables that we can define as a new multple variable type.
Example:

typedef struct StrTexInfoTr4 {
          WORD Attribute;
          WORD Tail;
          WORD Flags;
          float TopLeft[2];
          float TopRight[2];
          float BottomRight[2];
          float BottomLeft[2];
}TexInfoTr4Fields;

In tomb4 there are a lot of structures to host different infos about the game.
The above structure, for example, is that used for the tail infos, i.e. the infos about how placing every texture piece.
Once we declared the type of a new structure, we can using this type like it was a default variable type, like WORD, short, long.
For example following rows show different correct way to use the previous (above) definition of the StrTexInfoTr4:

StrTexInfoTr4* pTex;

StrTexInfoTr4 VectTailInfo[512];

StrTexInfoTr4 CurrentTail;

About above declaring we can see that the first has the pointer operator "*" (asterisk)

StrTexInfoTr4* pTex;

In fact, while in assembly we use the statement PTR (ex.. mov eax, dword ptr [ecx]) to signal the usage of a pointer, in C language we use the "*" to declare a pointer, while in the C instruction we'll use the "->" couple of charater to access to the pointed value.
For example:

WORD MyFlags;

MyFlags = pTex->Flags;

While when the declared structure is not a pointer but the real instance on our source, we can access to its single field using the "." (point) operator, in this way:

WORD MyFlags;
float OrgX;
float OrgY;
StrTexInfoTr4 CurrentTail;

CurrentTail.TopLeft[0] = OrgX;
CurrentTail.TopLeft[1] = OrgY;

Also for a vector of structures the access mode doesnt' change:

WORD MyFlags;
// read the flags of the tail structure with index 43
MyFlags = VectTailInfo[43].Flags;


The "union" used in structure declarations

This topic could be a bit complicated but I'll try to explain it in easy way.

A variable is like a box that can contain a value (a number, usually).

The name of that variable is like a label drawn on that box, to identify it.
With the "union" instruction we can drawn two or more names on same box.
Pratically we can have only one box, but we'll be able to call it, in the code, with different names.
For instance now look this structure declaration:

typedef struct StrObjectStuff {
          int Index;
          short OcbValue;
}ObjectStuffFields;

This is common declaration of structure.
If we create an instance of above variable in this way in our .cpp source:

          StrObjectStuff MyObject;

Then we'll be able to use variables of above structure in this way:

          MyObject.Index = 23;
          MyObject.OcbValue=0;
          
          if (MyObject.Index == IndexOfStatic) {
                    // our index is even than index of static...
          }

Well, we had already seen that...
But now we suppose that sometimes, for some weird reason, we have the need to save in "Index" variable of StrObjectStuff structure the intensity of the light of our object, instead of the index.
Could we save a different value in that "Index" variable?
Sure, if it is a common number, for the compiler it is the same about the meaning of that number.
For instance:

          MyObject.Index = GetLightIntensity();

The problem is only ours.
It will be weird typing a code where a light intensity will be saved in a variable named "Index"
We should always remember that value is not really an "index" in this case but an "intensity" of light.

Using a "union" instruction we could solve the problem, assigning to the memory space (4 bytes) of "Index" variable, two different names, in this way:

typedef struct StrObjectStuff {
          union {
                    int Index;
                    int LightIntensity;
          };
          short OcbValue;
}ObjectStuffFields;

Changing in above way the declaration of our structure, we have NOT added a new variable, like it could seem, but we have added only a new name for the same variable.
Pratically, in spite the name of this special instruction is "union", it should be more explicative if you see it like it was "ListOfNames" instruction.
With above new declaration of structure, we could use it in this way:

          StrObjectStuff MyObject;
          
          MyObject.LightIntensity = GetLighIntensity();

or, in other zone of the code:

          MyObject.Index = 31;

The interesting matter is that these two instructions:

          MyObject.Index = 125;
          MyObject.LightIntensity = 125;

they will have exaclty same effect. In both cases we are typing the same value in the same variable (box) of same structure.
It changes only the name, to get a better self-referenced code.

Unions and different Types

In previous paragraph we described the "union" only like a way to give to same variable two or more names, but in the reality we can also assign different types for same variable, or better to say, to same memory space.
For instance if we have this structure:

typedef struct StrObjectStuff {
          int Index;
          short OcbValue;
}ObjectStuffFields;

And we wish as in previous example, access to memory space (4 bytes) of "Index" variable, also with the name of "LightIntensity", we can use an "union" instruction.
But now we suppose that the light intensity could have decimal points, like "0.0124" and not only integer values like it happens with "int" type.
In this case we can change not only the name but also the "type" of variable, just only that the size (bytes of memory used to store that variable) was the same.
Since the "float" type is able to store decimal point values and it requires 4 bytes own like "int" type, we can change our structure in this way:

typedef struct StrObjectStuff {
          union {
                    int Index;
                    float LightIntensity;
          };
          short OcbValue;
}ObjectStuffFields;

And now we'll be able to store floating point numbers (of "float" type, with decimal points) in LightIntensity variable, while we'll get an error if we tried the same with an "int" variable.
Example:

          MyObject.LightIntensity = 0.334;

Above code will work fine, but in the case we tried to use this code:

          MyObject.Index = 0.143;

The compiler will return an error message, because it's not possible store a decimal point value in an (int)eger variable, like "Index".
Anyway the memory address used is the same for both variables: "Index" and "LightIntensity"


Other examples about declaration of variables

A declaration of variable create a zone of the memory where we can store numbers or texts.
The syntax is:

TYPE NameOfVariable;

When we wish declare a pointer of some variable type we'll place the sign "*" (asterisk) between the TYPE and the NameOfVariable:

TYPE * pNameOfVariable;

When we wish allocate a vector, i.e. a list of same type of variables, we add after the NameOfVariable a couple a squared parenthesis, with inside the number of items will form the list.

TYPE VetNameOfVariable[Number_of_items];

Examples:


Mathematical computations in C language

When in the Assembly equivalence there is a list of points ..... it means that there is no assembly equivalence for that C computation
Computation C syntax Assembly equivalence Notes
Assign value Alfa = 5; mov [Alfa], 5 ...
Addition Alfa = Alfa + 5;
Alfa += 5;
Alfa = Beta + 5;
add [alfa], 5
add [alfa], 5
mov eax, [beta]
add eax, 5
mov [alfa], eax
The double operator "+=" it used when we add a number to a variable.
In this case type:
Alfa = Alfa + 5;
or
Alfa += 5;

gets the same result
Subtraction Alfa = Alfa - 5;
Alfa -= 5;
Alfa = Beta - 5;
sub [Alfa], 5
sub [Alfa], 5
mov eax, [Beta]
sub eax, 5
mov [Alfa], eax
The double operator "-=" is used when a value is subtracted to a variable.
The instruction
Alfa = Alfa -5;
is the same than
Alfa -= 5;
Multiplication Alfa = Alfa * 12
Alfa *= 12;


Alfa = Beta * 12;
mov eax, [Alfa]
imul eax, 12
mov [alfa], eax

mov eax, [beta]
imul eax, 12
mov [alfa], eax
The double operator "*=" is when you mulitply a variable the same variable you use as result.

Alfa *= 12;
is the same that
Alfa = Alfa * 12;
Division Alfa = Alfa / 23;
Alfa /= 23;


Alfa = Beta / 23;
mov eax, [alfa]
idiv 23
mov [alfa], eax

mov eax, [beta]
idiv 23
mov [alfa], eax
The double operator "/=" is quando you divide a variable for a value and the you put the result in same variable.

Alfa = Alfa / 3;
is the same that:
Alfa /= 3;
Remainder of division Remainder = Alfa % 5; mov ecx, [Alfa]
idiv ecx, 5
mov [Remainder], dx
Example:

23 / 5 = 4 with remainder =3

In assembly the remainder of a divsion (DIV or IDIV instructions) is always stored in DX register
Power (square) Result = Alfa * Alfa;



Result = pow(Alfa, 2.0);
mov ecx, [alfa]
imul ecx, ecx
mov [result], eax

....
pow() is an external function, this means you have to include the source of this function, in your file.
If you get an error when you use pow() in your C function, you have to type at top of your source (after the other #include directives) the row:

#include <math.h>

note: pow() function want arguments and result in double format.
The double is alike float but with an higher precision.
Anyway we can convert any number in double, and the result in float or int
See the description about type conversion

Power raised to n Result = pow(alfa, 7);
Result = pow(alfa, 4);
.....
.....
See notes of Power (square)
Square root Alfa = sqrt(Beta); ....... sqrt() is an external function, this means you have to include the source of this function, in your file.
If you get an error when you use sqrt() in your C function, you have to type at top of your source (after the other #include directives) the row:

#include <math.h>

note: sqrt() function want argument and give the result in double format.
The double is alike float but with an higher precision.
Anyway we can convert any number in double, and the result in float or int
See the description about type conversion
returns a value return Alfa;

return Alfa+Beta;
mov eax, [Alfa]
ret
mov eax, [Beta]
add eax, [Alfa]
ret
In the reality the returning value is not a computation anyway it's interesting remember that when a function computes some value (or address) then it will have to return it to the caller code.
In a C function you use the return instruction to set what value place in eax register before exiting and coming back to the caller code.

In assembly we'use the eax code, too, but in this case we have also to place the ret instruction.

Note: remember that the assembly instruction:

ret 32

is not like, C instruction:

return 32;

The ret assembly instruction followed on same row by a number doesn't return that value in eax but it uses that value to compute how much bytes extract from the stack.
In the 32 flat assembly it's better never use ret in that syntax.
To return a value for caller code we'll use the syntax:

mov eax, 32
ret
Shift at left Alfa = Alfa << 4;
Alfa = Beta << 1;
shl [Alfa],4
mov eax, [Beta]
shl eax, 1
mov [Alfa], eax
...
Shift at right Alfa = Alfa >> 4;
Alfa = Beta >> 1;
shr [Alfa], 4
mov eax, [Beta]
shr eax, 1
mov [Alfa], eax
...
Increment by 1 Alfa++; inc [Alfa] ...
Decrement by 1 Alfa--; dec [Alfa] ...
and Alfa = Alfa & 7;
Alfa &= 7;
Alfa = Beta & 1;
and [Alfa], 7
and [Alfa], 7
mov eax, [Beta]
and eax, 1
mov [Alfa], eax
...
or Alfa = Alfa | 5;
Alfa |= 5;
Alfa = Beta | 3;
or [Alfa], 5
or [Alfa], 5
mov eax, [Beta]
or eax, 3
mov [Alfa], eax
...
exclusive or Alfa = Alfa ^ 4;
Alfa ^= 4;
Alfa = Beta ^ 8;
xor [Alfa], 4
xor [Alfa], 4
mov eax, [beta]
xor eax, 8
mov [alfa], eax
...
Not
One's complement
Alfa = ~4;
Alfa = ~Alfa;

Alfa = ~Beta;
mov [Alfa], ~4
not [Alfa]

mov eax, [Beta]
not eax
mov [Alfa], eax
The not is an unary operator, for this reason has no sense the istruction:

Alfa = Beta ~ 4
Pheraps when you type above istruction you meant:

Alfa = Beta & ~4

The complement's one is apparently a weird operation but it is very useful when we wish clear a single bit (or more bits) indifferently by its previous state.
If we wish clear the bit with value 8 in the variable [Alfa]
we can perform an and with the complement's one of 8

Alfa = Alfa & ~8;
or in syntetic form:
Alfa &= ~8;

and now the bit with value 8 will be 0
This is named "applying a bit mask"

In assembly it will be
and [Alfa], ~8

Note: the complement's one is like performing a XOR -1 on that value




Sign inversion Alfa = -Alfa;
Alfa = -Beta;
neg [Alfa]
mov eax, [Beta]
neg eax
mov [Alfa], eax
...
Get address of variable ptrMyVariable = &Alfa; lea eax, Alfa
mov [ptrMyVariable], eax
The & operator, when used as unary operator at left of a variable, returns the address of that variable, rather than its value.
Note that in assembly it's possible also to do that, using the syntax:

mov eax, offset Alfa

and it works like:

lea eax, Alfa

When you type the keyword "offset" in front of a variable you mean own "I want the address, rather than internal value, of this variable" in this case we could say that the precise assembly equivalence of the C++ "&" operator is own the "offset" keyword.
Anyway, in assembly, when in the right operand there are also registers it's better using the lea instruction:

lea eax, Alfa[ecx*2]


The pointers: examining in depth

The pointer is a variable that contains an address to access to another variable.
For example if we have this variable:

WORD MyNumber;

We can create a pointer for it in this way:

          pMyPointer = &MyNumber;

or in assembly:

          lea eax, MyNumber
          mov [pMyPointer], eax

How should it to be declared the "pMyPointer" variable?
Since it is a pointer we have to precede its name with the * (asterisk) sign:

WORD *pMyPointer;

And how could we use above pointer variable?
Everytime we wish read the value pointed to it, we have to precede its name with the * sign.

          alfa = *pMyPointer + 3;

In above istruction we put in alfa variable the content of MyNumber value + 3
If, for instance, the MyNumber variable had value = 5, now in alfa variable we have 8 (5+3).

Also for writing operations is the same:

          *pMyPointer = 0;

In above istruction we cleared (set = 0) the value of MyNumber variable using the pMyPointer to access to MyNumber.
But what does it happen if we use this istruction?

          pMyPointer++;

Please, note that the * sign is missing in above istruction.
Well, we know that the "++" operand increments by 1 a variable, but what has it been changed?
Not the MyNumber value because we omitted the "*" to point to that variable, but in this case we changed the address stored in pMyPointer variable.
This means that now the pMyPointer doesn't point to MyNumber variable but to the following word variable.
For example if we had declared:

WORD MyNumber;
WORD Radius;

In this case, after the pMyPointer++; instruction, now the address in pMyPointer has been increased to point to next word, and therefor, now it points to Radius variable.
Here, we can discover an interesting fact about C++ language. When you increase (or decrease) a pointer, the compiler will change the address stored in that pointer using as units not "1" but the size of the kind of pointer.
I mean that a WORD pointer will be increased by 2 to be able to point to next word (a word requires 2 bytes), while a DWORD pointer will be increased by 4 (because a dword requires 4 bytes)
For this reason when we performed the operation "pMyPointer++;" the address has been changed with Adr = Adr +2, to reach next word.
The relationship between pointers and vectors

The relationship between pointers and vectors

I know that this topic is rather disturbing because it could create more confusion than other.
Anway this "confusion" is already present in C language so it's better trying to deal with this problem immediatly.

The question is that a vector is seen from the compiler like a pointer.
For example:

WORD MyVect[30]; // a vector of 30 WORDs
WORD *pMyPointer; // an (empty) pointer to words

          pMyPointer = MyVect;

          pMyPointer[3] =0;

We can see two weirdness in above code:

Well, all above istructions are correct, and this because for the compiler a vector IS a pointer that contains the address to access to the list of values of that vector.
When we typed the istruction:
pMyPointer = MyVect;
we have simply copied the address from a pointer (MyVect) to another pointer (pMyPointer) of the same type (WORD). For this reason the compiler didn't say to us anything of bad.
In the second istruction:
pMyPointer[3] =0;
we did the opposite: we had used our pointer like it was a vector, but also this is correct and, in many circustances, very convenient.
Above istruction performs the same computations we hag gotten with following (traditional) code:

          pMyPointer +=3;

          *pMyPointer =0;

But with the advantage to have not changed the value in pMyPointer, preserving it for the future.
In both cases whe set 0 in the third (really the forth, with index=3, beginning from 0, they are 4 words) word from that was pointed originally by our pMyPointer.

To complicate furtherly the speech we can see this other situation:

char MyText[] = "Hello world!";
char *pMyPointer;

          pMyPointer = &MyText[6];

There are two questions about above code:

  1. Why, in this case, have we used the & operator?
    In previous code we showed the instruction:
              pMyPointer = MyVector;
    omitting the "&" and explaining that it was correct in this way.
    Why now have we used the & operator?
    Because when we use the squared parenthesis with the index ("[6]") it is not more a pointer but only a single variable (a word in that case).
    For this reason when we wish having a pointer refered to a single cell of a vector we have newly to use the "&" operator.
    Pratically it's like saying that only the single (alone) name of a vector is a pointer but not when we use it in the form "MyVect[4]"

  2. Other question is: what is the the benefit of the instruction?:
              pMyPointer = &MyText[6];
    Well, in above case, probably nothing, but in other cases it is useful memorize the position of some item (like a substructure) contained in a bigger zone whom we have only the pointer to the starting address.
    In above case now the pMyPointer will point to the text "world"


A pointer to access to vectors

We saw that we can having a pointer to a single variable in this way:

WORD MyNumber;
WORD *pMyPointer;

          pMyPointer = &MyNumber;

But what changes should we do, whether we wish having a pointer that points to a vector of word?
Well the answer is: absolutely no change!
Because for the compiler (and the C++ syntax rules) a pointer is a pointer and it's no important if after the first item there are other items of same type, or less.
It will be us, to choose to use it like a pointer to a single variable, or to a vector.
When we use with the syntax:

          *pMyPointer = 0;

          // or
          
          Alfa = *pMyPointer / 4;

We are using it like the pointer for a single variable. While we use it in following way:

          pMyPointer[4] = 12;
          // or:
          for (i=0;i<100;i++) {
                    if (pMyPointer[i] == 0) break;
          }

We use it like a pointer to a vector, or simply, like a vector.

Pointers to access to structures

We already talked about pointers and structures, see Pointers to access to structures , anyway in that case we spoke about the accessing from assembly language, now we'll speak about the (traditional) accessing whereby C++ language.
When we declare the structure in our source we can access to it in direct way, avoding the pointers.

// these are the protoypes of the structures in some source.h file (the "h" is for "Header file")
// this structure will be used as sub-structure from next structure
typedef struct StrBoxCollisione {
          short MinX;                              // 0x00
          short MaxX;                              // 0x02
          short MinY;                              // 0x04
          short MaxY;                              // 0x06
          short MinZ;                              // 0x08
          short MaxZ;                              // 0x0Ah
} robaBoxCollisione;

// our main structure
typedef struct StrStaticSlot {
          WORD IndiceMesh; // 00
          WORD SlotStatic; // 02
          StrBoxCollisione ViewBox; // 04
          StrBoxCollisione CollisionBox; // 10h
}robaStaticSlot;

// then in our source.cpp (cpp is for C Plus Plus, i.e. c++ source)
// we declare it

StrStaticSlot MySlot;

          // now we can use MySlot in following ways

          if (MySlot.IndiceMesh == 0) {
                    MySlot.SlotStatic =0;
          }

          MySlot.ViewBox.MinX = 0;
          MySlot.ViewBox.MaxX = 512;

          MySlot.CollisionBox.MinX =0;
          MySlot.CollisionBox.MaxX = 1024;


Looking above code, we see that to access to the fields of the structure we use the point "."
Differently, when we use a pointer to the structure we use the pointer operator: "->"


StrStaticSlot MySlot;
StrStaticSlot *pMyPointer;

          // get the address of myslot for the pointer
          pMyPointer = &MySlot;

          // now we can use pMyPointer in following ways

          if (pMyPointer->IndiceMesh == 0) {
                    pMyPointer->SlotStatic =0;
          }

          pMyPointer->ViewBox.MinX = 0;
          pMyPointer->ViewBox.MaxX = 512;

          pMyPointer->CollisionBox.MinX =0;
          pMyPointer->CollisionBox.MaxX = 1024;
          
In above code we should notice that we used the pointer operator "->" but not always.
For example in the istruction:

          pMyPointer->CollisionBox.MinX =0;

We used newly the "." between "CollisionBox" and "MinX" field.
The reason is that the rule is: "you use the pointer operator "->" when the variable at left is a pointer.
For this reason we use the pointer operator in first side: "pMyPointer->CollisionBox" because "pMyPointer" is a pointer, but in second side "CollisionBox.MinX" we used the "." because "CollisionBox" is not a pointer.
This speech could be described also in the opposite way:


// we have these two propttypes in some source.h file
// usata in room editor
typedef struct StrTextureInfo {
          WORD          Status;                                        // 00
          WORD          IndexAndFlags;                    // 02
          BYTE          Rotation;                              // 04
          BYTE          Triangle;                              // 05
          WORD          TriangleCouple;                    // 06
} RobaTexInfo;                              

// and main structure

typedef struct StrWall {
          WORD Flags;
          int RoomIndex;
          StrTextureInfo *pTexInfos;
}RobaStrWall;

// then in our code.cpp source:

StrWall MyWall;

          if (MyWall.Flags & 0x010) {
                    MyWall.pTexInfos->Status = 1;
                    MyWall.pTexInfos->Rotation = 0;
          }

In this case we access to a structure in direct way and in fact, after the "MyWall" variable name, we used the point ".".
Anyway in the istruction:

                    MyWall.pTexInfos->Status = 1;

We used the pointer operator "->" between "pTextInfos" and "Status" sub fields, and this because the pTexInfos (at left) is a pointer, as we can see looking the prototype of the main structure:

typedef struct StrWall {
          WORD Flags;
          int RoomIndex;
          StrTextureInfo *pTexInfos; // this is a pointer
}RobaStrWall;

The pointer of another pointer

Now we have to talk about the "horrific" double pointer!
Really the "double pointer" is not the right term, anyway it's easy to remember.
I mean when a pointer points to another pointer.
In this situation it's easy to get confused.

          WORD MyNumber;
          WORD *pMyPointer;
          WORD **p2Pointer;

          // get the address of MyNumber variable
          pMyPointer = &MyNumber;

          // get the address of pMyPointer variable
          p2Pointer = &pMyPointer;

          // now we change the value of MyNumber variable
          **p2Pointer-> 43;

When we have in a pointer the address of another pointer we have the horrific double pointer.
In this case we declare our double pointer with two "*" signs, and also when we use it to access to the final variable we'll have to use two asterisk (see above)
To understand well how it works, look this image:


Above image could coincide with following code:

char MyMex[]= "HELLO";

char *pMyMex;

char **p2Mexage;

          pMyMex = &MyMex;

          p2Mexage = &pMyMex;

In above case the address of MyMex = 460320, the address of pMyMex = 420080 and the address of p2Mexage = 406640

Now the obvious question is: why should we ruin so much our life!?
Unfortunately sometimes it happens.
It happens when we have to access to variables declared in other program.
This situation is that you have to deal with the plugin procjet, where you'll access very often to vectors and structrures declared in tomb_nextgeneration library or in tomb4 executable.
Anyway I tried to remove all double pointers where it was possible, and for the remaining cases I tried to get them visible using in their names the "p2" or "ptr2" suffix.
          

How to convert the types of variables

The C language gives to you a warning message everytime you mix variables of different types in a computation and this difference could produce a loss of numeric data.
For example this code:

          WORD Result;
          DWORD Alfa;

          Alfa=100;
          Alfa += 200;

          Result = Alfa+1;

it will generates the warning: "warning: conversion from 'unsigned long' to 'unsigned short', possible loss of data"
This message means: "the compiler noticed you copied a big number (DWORD) in a little variable (WORD), this could take a losing of digits if the number Alfa was bigger that could be hosted in a WORD variable.
Usally these warning are not really serious, anyway they are boring because when they are a lot, they confuse the debugging of the program, spreading too much messages.
To remove these warning you have two chances:


The cast-type with the (CASTING) operator

The casting is when you place a new type in front (at left) of a variable, enclosing it a pair of round parenthesis:

          WORD Alfa;
          DWORD Beta;
          long Omega;
          float MyFloat;
          BYTE * pVetBytes;
          char *pText;
          // change temporary the type of Beta from original DWORD to WORD
          Alfa = (WORD) Beta;

          // change temporary the type of Omega from original long to float
          MyFloat = (float) Omega;
          
          // change temporary the type of pVetBytes pointer, from BYTE* to char*
          pText = (char *) pVetBytes;

It's interesting notice that if you omit the casting "(new type)", the type conversion will happen alike but you'll receive a warning message.
In above examples we saw also that the pointer sign * (asterisk) is a part of the type and not only an attribute of its.

Main C statements (instructions)

In C glossay the instruction as named "statements", probably because they don't work alone but with a sepicific syntax that can "hug" a lot single istructions like computations and assignments.

The "if" statement

We saw that in assembly we perform a test on some variable (or register) with two instruction: the CMP (compare) operation between two variables and then a conditional jump in according with previous comparison, to jump to different points of the code.
In C it happen something alike but in this case we don't use jumps, but we group a block of instructions to perform when a given condition is true (or false).
Pratically it's the same thing but we have to learn to build C code avoiding the jump instructions.

int x;
char *pMex;

          y=0;
          pMex="";
          if (x > 3) pMex = "X is greater than 3";
          y=5;

In this case, when x is greater than 3 it will performed the instruction "pMex = "X is greather than 3""
If we wish perform more than one instruction, we can group many instructions in a couple of brackets { }

int x;
int y;
char *pMex;

          y=0;
          pMex="";
          if (x > 3) {
                    pMex = "X is greater than 3";
                    x = 0;
                    }
          y=5;

Now, looking this code, we could wonder: what does it happen if we want, after "x=0;" instruction, skip the following "y=5;" instruction?
We cann't use a jump...
In this case we can use the if statement in its complete syntax, using the "else" keyword.
The generic syntax of if stamement could be described in this way:


          if (condition is true) {
                     instructions
                    to perform when
                    the condition is true
          }else {
                    instructions
                    to perform when
                    the condition is false
          }

How we saw in previous example is not obbligatory the usage of "else", but in many circustances it's necessary for our targets.
Now, using "else" we can solve our problem, to skip the performing of "y=5;" instruction, when x grater than3

int x;
int y;
char *pMex;

          y=0;
          pMex="";
          if (x > 3) {
                    pMex = "X is greater than 3";
                    x = 0;
                    }
          else {
                    y=5;
                    }

Now, the "y=5" will be performed ONLY when the conditon ( x > 3) is false, and therefor it will be not performed when the condition is true.

.

The conditional operators used with IF

Operator Example Description
is equal
==
if (x == 0) ... A common error,of beginners about C language, is to use the single "=" sign to compare two values, while in C the single = sign is only for assignments, while for comparison we have to use the double equal ==.

The problem is that, by default, the compiler doesn't give any mexage because it could be a valid instruction in seldom circustances (assigning a value and verify its content in same moment)
Anyway if the compiler doens't warn you it's almost sure that you'll mistake very often using the assignemnt operator.
To avoid this problem it's necessary type at top of each source of your project, this pragma directive:

#pragma warning( error : 4706 )

Above directive tells to the compiler: "if I use an assignment in a IF condition, please say me that I mistaked with an error mexage"
The error mexage that it will be showed is:

error C4706: assignment within conditional expression

And now just performing a double click on that error mexage to see the row where you mistaked.

Remark: I've already inserted above pragma directive in all sources of your plugin, anyway if you'll add new sources to your plugin project, remember to insert also in these that directive.
is greater than
>
if (x > y) ... If first operand is greater than second.
Note that if the two operands are equal the condition will be false.
is greater or equal
>=
if (x >= y) ... if first operand is greater or equal than second, the condition is true
Please, note that it's not the same thing inverting the position of the two signs:

this is correct:

if (x >= y) ...

while this:

if (x => y) ...

is a syntax error.
is less than
<
if (x < y) ... When the first operand is less than second, the condition is true
is less or equal than...
<=
if (x <= y) ... When the first operand is less or equal than second, the condition is true.
Remember you cann't change the position of the two signs.
The only correct syntax is:

<=

while this:

=<

is a syntax error
is different than
!=
if (x != y) ... The "!=" is the opposite of "==".
If the two operands are different then the condition is true.

Note that in C language doesn't exist the "greater or less" operator that in some language (like visual basic) works in this way:

if (x <> 3) ...

Above syntax in C language is only a syntax error.
You have to use the != operator:

if (x != 3) ...
not
!
if ( !x ) .... The not "!" is an unary operator, it inverts the boolean value of the variable at its right.
To understand this operator it's necessary remember that when we test a variable omiting any conditional operator, the condition will be true if that variable is different than zero, while the condition will be false if the variable is zero.
For example:

int a;

a=3;

if (a) {
}

in above code the condition is true because value of a is 3, i.e. not zero, i.e. it is true.
If we place a not "!" in front of that variable:

if (!a) {
// code to perform when a is false (it is equal than 0)
}
The not operator inverts the result of a condition: if it was true, it becomes false and vice versa.
This operator works fine also with macro conditions grouped in parenthesis.

if (!(a > 3 || a < -3)) {
// the condtion will be true, and this code will be performed,
// when (a <= 3 && a >= -3)
}
and bits
&
if (x & 1) ... The single & character, used as binary operator, works like an AND to test the single bits of the two operands.
It works like the TEST assembly instruction.
You use the binary & when you wish perform a condition about the single bits of a variable.

Example:
WORD Mask;


Mask = 10;

if (Mask & 2) {
// the condition is true because 10 is 8 + 2 bit values, so the bit
// value 2 is present
}
Just that at least one bit was present in both operand two give a true result.
and conditions
&&
if (x == 3 && y == 0) ... The conditional and "&&" permits to link two or more condition, the result will be true if all the conditions are true.

example:

a=3;
b=5;
c=0;

if (a > 1 && b < 6 && c !=0) {

}

above condition is false, because "a > 1" is true, "b < 6" is true but "c != 0) is false because c had to be different than zero to be true the condition.
We can use also nested round parenthesis to group complicated conditions

if (c == 0 && (a == 0 || a == 3))

above condition is true
or conditions
||
if (a == 0 || b == 0) ... The conditional or "||" compares two or more conditions, the result will be true if at least one of them is true.

Example:

a = 4;
b = 12;
c = -3;

if (a == 12 || b == 12 || c == 0) ...

Above condition is true, because the sub-condition "b == 12" is true and, in spite of the others are false, with the or just that one OR another was true to get true the whole condition.


The switch() case statements

The switch statement is a sort of advanced conditional statement where we can perform a long list of conditions, keeping separate code for each different true condition.
For exampe if we wish perform different code in according with the value of "a" variable, using the "if" statement the code could be long and chaotic

          if (a == 1) {
           // ... code
          }

          if (a == 2) {
           // ... code
          }

          if (a == 3) {
           // .. code
          }

          if (a == 4) {
           // ... code
          }

          if (a == 5) {
           // .. code
          }

          if (a == 6) {
           // .. code
          }

In situation like above, it's better using a swith case.
The syntax of switch statement is:

          switch (Value) {
          case Number:
           // code if Value=Number
           break;
          case OtherNumber:
           // code if value=othernumber
          default:
           // code if value is different than all supplied above cases
          }

The previous code to test the "a" value, with switch will become:

          switch (a) {
          case 1:
                    // code for a=1
                    break;
          case 2:
                    // code for a=2
                    break;
          case 3:
                    // code for a=3
                    break;
          case 4:
                    // code for a=4
                    break;
          case 5:
                    // code for a=5
                    break;
          case 6:
                    // code for a=6
          }


The "break" instruction in the switch statement

The break; instruction move the control (point where the code is performed) after the whole switch () { } statement.
In the most cases we place a "break;" at end of each code for each case but sometimes it could be useful omit the break and also the code for that case.

          switch (index) {
          case 1:
                    alfa= 100;
                    break;
          case 2:
          case 3:
                    alfa = 200;
                    break;
          }



In above code, we have not placed the "break" after the "case 2:" and neither a code to be performed.
In this situation, when the index variable will be equal than 2, will be performed the case 2 but since there is nothing and netiher a break to go out of the switch, it will be performed the case 3 and the istruction "alfa =200"
This usage permits ot have a sort of OR of two or more cases, like we had written, with the if:

          if (alfa == 1) {
                    alfa=100;
          }
          if (alfa == 2 || alfa == 3) {
                    alfa=200;
          }


The "default" istruction in the switch statement

The default: keyword work like a case and it will be performed only when the all other cases will have a false conditions.

          switch (index) {
          case 1:
                    // code for 1
                    break;
          case 5:
                    // code for 5
                    break;
          case 0:
                    // code for 0
                    break;
          default:
                    // code for any other value of index
          }

Above syntax should be more vague using if statements

          if (index == 1) {
                    // code for 1
          }
          if (index == 5) {
                    // code for 5
          }
          if (index == 0) {
                    // code for 0
          }
          if (index != 1 && index != 5 && index !=0) {
                    // code for other values
          }


The for() statement

The for statement allows to manage a loop, i.e. a group of istructions that will be repeated many times.
Usually we'll use the for to manage a vector, using an index to elaborate each cell of the vector.
The for in this situation will be used to increase the index variable and hosting the code to parse the vector.
The general syntax of for is:

          for (index=0 ; index < number_of_items ; index++) {
                    }

Pratically in the round parenthesis we have two semicolon characters ";" that create three fields: the first (at left) is to initialize the index to its first value (usually 0).
The second (in the middle), contains a condition to verify when the loop will be completed, while the third, at right, will have the istruction to increase our index.
All the code enclosed in the following pair of brackets will be performed many times, how it will be increasing of index from its inital value upto when the condition will become false.

int MyVector[100];
int index;
int NowValue;

for (i=0 ; i < 100; i++) {
          NowValue=MyVector[i];
          // ... other code to elaborate NowValue
}


The "break" instruction in the for statement

Like for The switch() case statements , also in the for statement you can use the break instruction.
When the break will be performed the loop will be stopped and it will be performed the first istruction after the current for.
While in switch() statement is normal use the break istruction, in the for it is an exception since it stop the full parsing of the vector.
It sometimes happens that we check a further condition in the parsing code and when this condition is true the loop will be stopped.

char *ControlValues(int *pVetValues)
{
int i;
int CurrentValue;
char *pMessage;
pMessage = "That's ok";
for (i=0;i<100;i++) {
CurrentValue = pVetValues[i];
if (CurrentValue < 0) {
pMessage = "ERROR: invalid value less than zero";
break;
}
// other code to manage the currentvalue
}

return pMessage;
}

In above code there is a parsing where we check if there are invalid vales in the vector, like the negative numbers. When an invalid number has been found the loop will be stopped with the break; istruction and the commnd will pass to the "return pMessage; instruction

The while() statement

The while statement is another variant of the for() statement.
Also the while manages a loop, for a given group of istructions, but in this case there is only the check of the condition in automatic way, while the initilalization of variables (index or other) and the increasing of these variables will be managed in custom way by the code and not by the while() statement
The general syntax of while statement is:

          while (condition) {
           // group of instruction
           // to perform untile the while condition is true
          }

Usually you'll use the for() when you wish parse a vector where you know all items available and you wish parse all these items, while you'll use the while statement when it's not clear how much items you'll have to parse, because the condition of end loop will be discovered only parsing the vector and not at begin.
Example:

#define MAX_ITEM 100

int i;
short VetItems[MAX_ITEMS];
short ValNow;
          // initilize index to parse the vector
          i=0;
          // parse the vector
          while (i < MAX_ITEMS) {
                    ValNow = VetItems[i];
                    if (ValNow == 0) {
                              // found signal of "end list"
                              break;
                    }
                    //perform management of current value ValNow
                    /// ....

                    // increment index to parse the vector
                    i++;
          }                              
          
How we can see, the break instruction has been used to go out from the loop when the value of "end list" has been found





Common error messages from C++ Compiler

In this chapter we'll see the most common error messages you get when you build your plugin project, and the possible solutions.

As we'll see, there are some classical errors that happen very often to the beginners because the C syntax is rather fussy for the newbies

Error: 'x': undeclared identifier

This error is easy to understand: a variable has not been declared, but it is sometimes hard to understand the reason, since we believe to have declared it.
Example:

void MyFunction(void)
{
          int MyFirstValue;
          WORD MyVect[20]={1,3,4,4};

          MyFirstValue = MyVect[0];

          if (MyVect[1] > MyFirstvalue) MyFirstValue=2;

}

Above code will generate the error:

error C2065: 'MyFirstvalue' : undeclared identifier



Solution
In C++ language, the variables: "MyFirstValue" and "MyFirstvalue" are different, because just having different lower/upper case to identify different variables.
When you got that error, and you believe to have already declared that variable, look better the lower/upper case!

Note: In assembly the situation is different, you can mix the upper/lower case.
In assembly the variables (or label for jumps, or subroutine names but not for macros that are C "creatures") "MyLabel" and "myLabel" or "myLABEL" are the same.
But remember that in C is another matter...

Another reason of "undeclared identifier" error

Another possible reason of the "undeclared identifier" (when you believe to have declared it) happens when you declare a variable (or a function), in a source (alfa) but then you use it in another source (beta).
Example:


// ------------ content of Alfa.cpp source --------------------

WORD MaxValue=-1;


int EaterApples(char FirstFruit[])
{
          int i;

          for (i=0;i<10;i++) {
                    if (FirstFruit[i] == 'A') return i;
          }

return -1;

}

// ----------- contents of Beta.cpp source -------------------

// internally of some C function (of Beta.cpp source)

          if (EaterApples(pTexts)==-1) {
                    MaxValue =-1;
          }
-------------------------------------------------------------------

The above code, in the Beta.cpp source, generate two "undeclared identifier" errors: one for the MaxValue variable, and the other for the EaterApples() function.


Solution
To solve the problem you have to declare as "extern" the variable MaxValue at top of Beta.cpp source:

// ----------- contents of Beta.cpp source -------------------
extern WORD MaxValue;

Please, note that in the "extern" declaration you cann't initialize it (like we did in Alfa.cpp source: "WORD MaxValue=-1;") because we can initalize a variable only once.

Also for the EaterApples() is the same, but in this case the "extern" keyword it's not necessary.
You'll copy the first row of the EaterAppels function from Alfa.cpp to Beta.cpp, placing a ";" at end, and omitting the brackets "{ }" and their content, of course

// ----------- contents of Beta.cpp source -------------------

// function declared in other sources
int EaterApples(char FirstFruit[]);


Error 'x' : redefinition; different type modifiers

Also this error is rather deceptive, because you read "redefinition" but you had defined that function only once....
Example:


void DrawBox(int x, int y, int sizex, int sizey)
{

          DrawLine(x, y, x+sizex, y);
          DrawLine(x+sizex, y, x+sizex, y+sizey);
          DrawLine(x, y+sizey, x+sizex, y+sizey);
          DrawLine(x, y, x, y+sizey);

}

void DrawLine(int FromX, int FromY, int ToX, int ToY)
{
          // .... other code ....

}

For above code we'll receive from the compiler some error messages, and they seem a joke:

error C2065: 'DrawLine' : undeclared identifier
error C2373: 'DrawLine' : redefinition; different type modifiers

Why "DrawLine" is "undeclared"??
Why should be it a "redefinition"?
About "different type modifiers" WTF??


Solution.
The only problem is that we called the DrawLine() function, first (above in the shource) of its declaration.
When the Compiler reaches the drawbox function, it yet doesn't know the "drawlinee" function, and gives an error "undeclared indentifier".
Now it remembers that DrawLine() exists because we used it, but it assigns as default declaration the prototype "void DrawLine(void)".
When it, moving down, meets the declaration of "void DrawLinee(...)" it says "redefinition", and then it sees also that the declaration is different.

Ok, the compiler is mad.

Anyway the solution is easy, just moving the DrawLine() declaration above the first point where we use it.
So we can change the source in this way:

void DrawLine(int FromX, int FromY, int ToX, int ToY)
{
          // .... other code ....

}

void DrawBox(int x, int y, int sizex, int sizey)
{

          DrawLine(x, y, x+sizex, y);
          DrawLine(x+sizex, y, x+sizex, y+sizey);
          DrawLine(x, y+sizey, x+sizex, y+sizey);
          DrawLine(x, y, x, y+sizey);

}

And now all works.
Anyway in some circustances it could be boring the cut & copy of a whole function, because this change, in the sorting of the functions, it could create newly the same problem but with other functions.
To avoid this problem we can solve better above problem in this way:

// at top of current source:
void DrawLine(int FromX, int FromY, int ToX, int ToY);


void DrawBox(int x, int y, int sizex, int sizey)
{

          DrawLine(x, y, x+sizex, y);
          DrawLine(x+sizex, y, x+sizex, y+sizey);
          DrawLine(x, y+sizey, x+sizex, y+sizey);
          DrawLine(x, y, x, y+sizey);

}

void DrawLine(int FromX, int FromY, int ToX, int ToY)
{
          // .... other code ....

}

We placed the definition of DrawLine() function as it was an extern function, in spite it is in same source.
This is fine and it is the most common solution to this pronblem.

Error C4706: assignment within conditional expression

We had already talked about this error (Mathematical computations in C language ), about the assignment operation.
Example:

          if (i = 0) {
                    x=i+1;
          }

In above code we get this error because, in the "if (i=0)" instruction, we meant perform a condition, but we used a single = character and in this case we did only an assignmento, to copy 0 to i variable.


Solution
You should remember to use always the double equal (==) when you wish perform a comparison

          if (i == 0) {
                    x=i+1;
          }

And now the error has been fixed

Error C2440: '=' :cannot convert from 'xxx' to 'yyyy' or "C2446: '==' : no conversion from 'xxx' to 'yyy'

Another very common error message...
Everytime you mix different types in some computation or assignment the compiler will show above error.
Here you should understand the difference between this ERROR "cannot convert" and the WARNING "conversion from 'xxx' to 'yyy', possible loss of data" messages.
In this first case, it's a real error and we have to change our code, while in the second case the compiler is only worry that the different size of two variable could create problems in some (seldom) circustance. We had already talked about that warning message (see How to convert the types of variables chapter).
Currently we are talking about ERROR, this means that we'll have really to change something in our code because there is a real error.
There are a lot of wrong mixage we could do, but we'll analys here only the most commons.
Example:

          char *pCar;

          char MexName[]="hello";

          pCar = &MexName;

In above code we'll get the error message:

error C2440: '=' : cannot convert from 'char (*)[6]' to 'char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast


Solution
The error has been to place that "&" character in front to "MexName".
The MexName is alread a char pointer, it's not necessary (and wrong) using the "&" operator to get its address.
Omitting the "&" all will work fine.

          char *pCar;

          char MexName[]="hello";

          pCar = MexName;


Example of: "no conversion from 'xxx' to 'yyy'" error


          char MyText[]= "Hello world";
          DWORD i;

          for (i=0;i <strlen(MyText);i++) {
                    if (MyText[i] == "w") break;
          }

Above text scan the MyText[] vector (the "strlen()" function returs the number of character of given string).
We'll receive the error:

error C2446: '==' : no conversion from 'char *' to 'int'

refered to the line:

          if (MyText[i] == "w") break;

The error message get confuse us: what is the "char *" type, and what the "int" type?
We thought that MyText[i] is "char" and also "w" is a char.


Solution
The problem is that we used quotes for "w" character while we had to use the apostrophe character ' to encose the w.

          char MyText[]= "Hello world";
          DWORD i;

          for (i=0;i <strlen(MyText);i++) {
                    if (MyText[i] == 'w') break;
          }

Now we replace the quotes (") with the apostrophes (') and the error disappears
Note: we can use the quotes for strings but not for single characters.
When we use quotes, we create a constant string, i.e. a vector of char types.

Another example of error: "no conversion from 'xxx' to 'yyy'"


          WORD MyVar;
          WORD *pPointer;

          if (MyVar == pPointer) return NULL;

For above code, and in paritcular way the line "if (MyVar == pPointer)...", we'll get following errors:

trng.cpp(69) : error C2446: '==' : no conversion from 'unsigned short *' to 'int'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
trng.cpp(69) : error C2040: '==' : 'int' differs in levels of indirection from 'unsigned short *'

In above error message the news is that "....differs in levels of indirection ..."
When the compiler speaks about "indirection" it means we mistaked someting about pointers.


Solution
In fact, we used the pPointer of WORD but we omitted the "*" indirection operator and the compiler had to compare a WORD type (MyVar) with a pointer (WORD *), and this indirection is not possible.
We had to type in this way:

          WORD MyVar;
          WORD *pPointer;

          if (MyVar == *pPointer) return NULL;

// or also in this way
          if (MyVar == pPointer[0]) return NULL;


The second form ( unusual because we access only to first word to the pPointer) is more clear to understand we are accessing to a single word.
Anyway both syntax are fine.

Errors about indirections and pointer arguments: "error C2100: illegal indirection"

A lot of misunderstandings borns in the management of the pointers.
We'll give a list of most common mistakes, anyway I suggest to read carefully the The pointers: examining in depth chapter, too

// we have a function declared in this way:
void MyFunction(WORD *pPointer);

// we see some (wrong) ways to pass to it an argument

WORD MyVar;
WORD *pWordZone;

          MyFunction(MyWar);

          MyFunction(*MyVar);

          MyFunction(*pWordZone);

          MyFunction(pWordZone[0]);

          MyFunction(&pWordZone);

Sad to say but all above calls will generate error message.
The right ways to call the MyFunctions() are these:

WORD MyVar;
WORD *pWordZone;

          MyFunction(&MyWar);

          MyFunction(pWordZone);

About the reason of these mental lapse, I believe that it was because we are get confuse by the declaration of a pointer:

WORD *pMyPointer;

That asterisk gets confuse us.

We should remember that is different the usage of the asterisk in the declaration, respect that usage in the instructions.
When we declare a pointer, we use the asterisk to inform the compiler that variable is a pointer.
But when we use in the code we'll use the asterisk only when we wish use that pointer like a single variable.
For example in this instruction:

WORD MyNumber;
WORD *pMyPointer;

          MyNumber = *pMyPointer;

The "*pMyPointer" in assignment instruction, is like a single word, not a pointer.
While if we use it alone:

WORD MyNumber;
WORD *pMyPointer;
WORD *pOtherPointer;

          pOtherPointer = pMyPointer;

Like it happens in last instruction "pOtherPointer = pMyPointer;", that "pMyPointer" alone has been used as a pointer.
This gets confusion.

Error C2601: 'FunctionName' : local function definitions are illegal

This is a very boring error to fix, above all, if you don't understand its meaning.

bool IsGood(int Number)
{
          if (Number < 0) {
                    if (Number == -10 || Number == -100) return true;
          }else {
                    if (Number > 1000) {
                              return false;
           }
return true;
}
                    
int DrawAtom(int x, int y)
{
// ..... some code .....
return 0;
}                    


Compiling above code, we'll get the error:

error C2601: 'DrawAtom' : local function definitions are illegal
          
Probably we'll get also many other errors like above, one of each function name following the IsGood() function.


Solution
In spite above code could generate tons of errors, the real error is only one: we missed to type a closed bracket "}" in the if statement in the IsGood() function.
Remember that when your read the error "local function definitions are illegal" the reason is almost always this: a missing closed bracket.
Therefor, to solve it, you have to analyse the function above the name function in the error message (in our example the error speaks about 'DrawAtom' and so we have to analyse the function above in the source to the DrawAtom, and in our source it is the "IsGood() function", and try to count the number of open / closed bracket until to discover where we missed the closed bracket.
The code after our correction will be this:

bool IsGood(int Number)
{
          if (Number < 0) {
                    if (Number == -10 || Number == -100) return true;
          }else {
                    if (Number > 1000) {
                              return false;
           }
          } // <= here we missed a closed bracket
return true;
}
                    
int DrawAtom(int x, int y)
{
// ..... some code .....
return 0;
}                    

And now the tons of error messages will disappear.

Error C2143: syntax error : missing 'x' before 'y'


bool IsGood(int Number)
{
          if (Number < 0) {
                    if (Number == -10 || Number == -100) return true;
          }else {
                    if (Number > 1000)
                              return false;
          
                    }
          }
return true;
}

Above code will generate (a lot of) errors like:

trng.cpp(77) : error C2143: syntax error : missing ')' before 'constant'
trng.cpp(77) : error C2059: syntax error : ')'
trng.cpp(77) : error C2143: syntax error : missing ';' before '{'



Solution
The reason of these error is the opposite of previous error we spoke local function definitions are illegal
In that case the problem was a missing closed bracket, while now the problem is a missing OPEN bracket.
We fix the problem discovering where the open bracket is missing and type it.

bool IsGood(int Number)
{
          if (Number < 0) {
                    if (Number == -10 || Number == -100) return true;
          }else {
                    if (Number > 1000) { // <--- here it was missing an open bracket
                              return false;
          
                    }
          }
return true;
}



Warning C4715: 'FunctionName' : not all control paths return a value

This message is described as "warning" but for me it's stupid say in this way: it is own an error.
It happens in situation like this:

bool IsGood(int Number)
{
          if (Number < 0) {
                    if (Number == -10 || Number == -100) return true;
          }else {
                    if (Number > 1000) {
                              return false;
                    }
          }

}

With above code we'll receive this error message:

warning C4715: 'IsGood' : not all control paths return a value



Solution
The IsGood() function should return a value, true or false, but it's missing a return with some true/false, at bottom of the function.
We can fix this bug in this way:

bool IsGood(int Number)
{
          if (Number < 0) {
                    if (Number == -10 || Number == -100) return true;
          }else {
                    if (Number > 1000) {
                              return false;
                    }
          }
return true; // <-- we returns a value also here
}


Warning C4101: 'VariableName' : unreferenced local variable

This is another common warning message.
It means simply that you declared a local variable in some of your functions but you have never used it in the code.
The solution is simply to remove the declaration of that variable.

Example:

void GetMaxValue(int Arg1, int Arg2)
{
          int MaxValue;
          int SwapValue;

          MaxValue=-1;
          if (Arg1 > MaxValue) MaxValue=Arg1;

          if (Arg2 > MaxValue) MaxValue=Arg2;

          return MaxValue;
}

With above code you'll have the warning:

Warning C4101: 'SwapValue' : unreferenced local variable

It's not a serious problem. Probably, previously, you had written the code in another manner and you used the "SwapValue" variable, but after some change you removed that part of the code and now that variable is yet declared but never used.
The solution is simply to remove the line "int SwapValue;"


The auto member list skill stopped working

In the reality this is not an error message from the compiler but it is own an error of the compiler.
We saw the auto-member list skill when we spoke about A trick to get easily the path of all subfields of a structure in How to combine assembly with the C++ skills
Well, sometimes that skill stops working. It could happen that it works only partially, too. Where with some structures it works and with others it doesn't.


Solution
The is a well-known bug, and to fix it I did a command in TrngPatcher utility. Launch TrngPatcher, quit Visual Studio, and choose menu command "Tools->Fix VC6.0 error Auto Member list"


Error LNK1207: incompatible PDB format

This error should happen only with Visual Express 2010 compiler.
It is a bug of the compiler and not an error in your source.


Solution
The is a well-known bug and you can fixing it using, yet, TrngPatcher bug this time, choosing the menu command: "Tools->Fix Visual C++ 2010 errorLNK1207