In most programming languages, especially imperative languages, a “variable” is actually two things: a name and a storage location. The storage location is a block of memory where a value can be stored and retrieved. The variable's name is often called an identifier. An identifier is a way to refer to some object in the program, in this case a storage location. A variable has a scope, which is the part of the program where the variable's name refers to the variable.
For example, consider the following C snippet.
int foo;
void myfunction(void) {
float foo;
… /* Here the identifier foo refers to the variable that's of type float. */
}
/* Here the identifier foo refers to the variable that's of type int. */
This snippets declares two variables. The two variables happen to have the same name: both are called foo. They're distinct variables, refering to distinct storage location, same as if they'd been called by different names. The scope of the foo variable that's of type float is the function myfunction: inside the code of myfunction, the identifier foo refers to this variable; outside the code of myfunction, the identifier foo refers to some other variable, or none at all. The scope of the foo variable that's of type int is the file where it's declared; the identifier foo refers to this variable everywhere is the whole file, except for the functions (or more generally blocks¹) which declare another variable that's also called foo. The local variable foo is said to shadow the global variable foo.
A variable whose scope is a whole file is usually said to be global. A variable whose scope is a function, method, block, etc. is usually said to be local. In the example above, the int-typed foo is a global variable and the float-typed foo is a local variable, local to the function myfunction.
The scope of a variable is the part of a program where its name refers to that variable. This is not always the same thing as the part of the program where the storage location exists. There is some correlation between the two, because it's usually undesirable to have a name for a storage location that doesn't exist, and it's often desirable to have a name for storage locations that do exist.
In C, the time during which a storage location exists is called its duration. The duration of a global variable is the whole program execution (“static duration” in C jargon, but that jargon doesn't extend to other languages, unlike most of the terms I used in this answer). (That's in C and some other langauges; in many other languages the duration of a global variable starts when the variable is defined.) The duration of a local automatic variable is the time during which the block containing it is executing. Note that “automatic” refers to the duration, not to the scope; “automatic” is not the opposite of “global”, “local” is. In C, you can't have automatic duration at a global scope, but you can have static duration at a local scope, with a variable that's declared static or extern.
void myfunction(void) {
static int s;
extern int e;
}
/* Here s and e are not defined */
The duration of both s and e is the whole program execution, but their scope is only the function myfunction: the names e and s are not valid outside that function. The difference between static and extern is that the variable s cannot be accessed from another scope, whereas e is the same variable as any other extern e in any scope.
Coming back to the foo example above, since two variables in different scopes have no relation, altering foo in myfunction has no impact on the global foo. They're unrelated variables, they just happen to have the same name.
It would be possible to rename the local variable foo to avoid having a name conflict. If you change all occurrences of foo in the code of myfunction to a different name that isn't used elsewhere in the program, you get an equivalent function.² This renaming process is known as alpha conversion in programming language theory.
The main reason programming languages allow programmers to pick the same name for different variables is that doing otherwise makes it difficult to write large programs and especially to write programs in pieces. If adding a library to your program meant that you had to rename some of your local variables in unrelated parts of your program to avoid conflicts, it would be a nightmare. (As it is, C only has global names for functions, which can be troublesome.)
Basically all languages allow variables in unrelated scopes to have the same name. C also allows shadowing: defining a variable in a scope hides any variable by the same name in a surrounding scope. This is common, but not univeral. For example, in Java, if you define a variable in a block, you can't define another variable by the same name in a nested block. The advantage of this restriction is that it prevents a source of confusion: a programmer might inadvertently use the name to refer to the variable from the outer scope, and not realize it instead refers to the variable in the inner scope. The downside of this restriction is that it makes some program transformations impossible without renaming the variable.
void myfunction(void) {
int x = 1;
if (…) {
int x = 2; // allowed in C, forbidden in Java
printf("%d\n", x); // prints 2
}
printf("%d\n", x); // prints 1
}
Some languages have a way to refer to a variable that's shadowed, but it's uncommon. C has no such way, but you can refer to the storage location of the outer variable if you have a pointer to it.
¹ More precisely, the scope of a variable defined in a block runs from the variable definition to the end of the block. If there is an outer scope with a variable of the same name, it's that same part which is excluded from that outer scope.
² This only works in languages where variable names are not significant. Actually, I lied here, because C can make variable names significant via the preprocessor. C is quite a complex language… If that preprocessor feature isn't used, variable names are not significant.