As a rule, I don't like to put executable code in a header file. Rather, I put it in another file with a *.cpp extension. I also dislike the String class because it bloats the code. So for your test program, you could try:
// main program aTest.ino
#include "common.h"
extern int pos2; // Note the declaration here; not defintion
void setup()
{
Serial.begin(9600);
}
void loop()
{
char tStr[] = "1234567890";
int tPos = posStr(tStr, pos2);
Serial.print("Length is: ");
Serial.println(tPos);
Serial.println(tStr);
}
Many programmers are really sloppy about using the terms "define" and "declare". In this file, we declare pos2. The extern keyword says to the compiler: This variable is defined in some other file, but let me use it in this file as an int." Because pos2 is defined in the header file, think of the compiler typing in two question marks after pos2 in this file, which is a message to the linker to fill in the actual memory address of where pos2 really lives. (Yeah, I've taken a few liberties...)
In the header file, common.h we have:
int pos2 = 5; // Definition of pos2
int posStr(char aStr[], int aPos); // Declaration of posStr()
When the compiler sees the first line in the file, it allocates memory of pos2 which means it is a definition of pos2. The second line is a function prototype, which allows the compiler to perform type checking on the parameters and return type. Because there is no code for the function, it too is a declaration. All function prototypes are declarations, not definitions.
The third file is the *.cpp file, which I called posStr.cpp:
#include <string.h>
int posStr(char aStr[], int aPos)
{
strcpy(aStr, "Hello");
return strlen(aStr);
}
Because the code for the function is presented here, memory is allocated for the function, which makes this a function definition. The three files together form your program. In the IDE, you can use the little down arrow on the extreme right side of the IDE, below the "magnifying glass" to add and name file tabs in your program.
The distinction to remember is:
declaration: forms an attribute list (name, data type, scope, etc.) but does NOT allocate memory
definition: also forms an attribute list, but also allocates memory for the variable.
The extern keyword creates a data declaration for a variable (its attribute list) that is defined in some other file. This declaration allows you to use the variable in a file where it is not defined. Many programmers use declaration when they really mean definition.
Edit: Steve's way of preventing a "double include" using the #ifndef is a good practice to follow