Reputation: 15217
C has no namespaces, but does it strictly forbid redeclarations, when compiler silently overrides some names by names from includes? Is it valid idea, that I can name my functions, structs, types whatever I want to, and rely on redeclaration compile-time error in case if name clashes?
For example, if I name my struct like struct message
or whatever else widespread name, I don't want, that some dependency of dependency would break because of that, or on the contrary override my name.
Upvotes: 2
Views: 130
Reputation: 123558
TL/DR Version - You can only rely on the compiler catching name clashes for you when you have two different objects in the same scope with the same name, or when you try to use the same name for an enumeration constant and a function or object name, or when you try to use the same tag name for different struct
, union
and enum
types, or when you try to use the same typedef name for different types. Otherwise, your object declarations may "shadow" other object declarations/definitions in the includes.
Edit - See section 7.1.3 of the C 2011 standard for a description of identifiers reserved for use by the implementation. Avoid using identifiers with leading underscores or a leading to
, is
, or str
, and you should be reasonably safe, at least as far as the standard libraries are concerned.
James Michener Version - C has namespaces (see section 6.2.3 of the C 2011 standard), they're just not user-defineable:
struct
, union
, and enum
tag namesThus, the following code is legal:
void foo( void ) // ordinary identifier
{
struct foo { // tag name, disambiguated by presence of struct keyword
int foo; // member name, disambiguated by struct declaration syntax
} bar;
...
bar.foo = ...; // member name, disambiguated by . operator
goto foo; // label name, disambiguated by goto
...
foo: ... // label name, disambiguated by label syntax
}
Identifiers may "shadow" identifiers defined in an outer scope:
char *i; // file scope identifier
void blah( void )
{
int i; // block scope identifier, "shadows" file scope i
if ( some_condition() )
{
double i; // block scope identifier, "shadows" outer block scope i
...
}
...
}
Each of the above i
s refers to a different object.
The same identifier can be used in different scopes:
void foo( void )
{
int i; // local to foo
...
}
void bar( void )
{
int i; // local to bar
...
}
In the case above, the identifier i
is used for two different objects.
If an identifier has external linkage, then identifiers in different translation units can refer to the same object:
/**
* foo.c
*/
void foo( void )
{
extern int blah; // will resolve to the object defined in bar.c
printf( "blah = %d\n", blah );
}
/**
* bar.c
*/
int blah = 5;
void bar( void )
{
foo();
}
What you cannot do is have two different objects in the same scope with the same identifier, or use an enumeration constant as a function or variable name, etc.:
void foo( void )
{
enum bar { foo, // illegal, clashes with identifier for function
bar,
bletch };
enum bar bar; // illegal, object name clashes with enumeration constant bar
int i;
double i; // illegal, clashes with previous object definition
...
}
Upvotes: 1
Reputation: 78953
To give you a more pragmatic answer: yes, names that you give to your types, struct
, functions etc can easily clash with names that other libraries use. And there is no automatic feature that would magically repair that.
This is one of the severe weaknesses of the C programming language. The C library itself even reserves a lot of names and prefixes for its own use, and it is not always simple to know what names you can use safely or not. E.g if you'd include the <string.h>
header file all names starting with str
would be forbidden for your own application code, e.g something like strip
wouldn't be allowed for you.
This is why packages that are supposed to be included into other code, usually use a nameprefix for all their names that are globally visible. E.g POSIX' threads use the prefix pthread_
.
Upvotes: 1
Reputation: 17503
The content associated with a struct, union or enum tag can only be defined once in the same scope. Also, the tag can be used in only one of struct, union or enum in that scope as they share the same namespace within that scope.
N1570 ISO/IEC 9899:201x Draft §6.7.2.3 Tags
Upvotes: 1
Reputation: 145899
C has no namespaces
C has a some simple name spaces (not in the sense of C++):
It has different name space for identifiers: structure tag names, structure member names, label names, macro names...
struct a;
int a = 0; // valid, different name space
You can have multiple external declarations:
extern int y;
extern int y; // valid
With tentative definitions, you can have multiple declarations:
int z, z; // valid at file scope
You can have "benign redefinitions" of macros:
#define BLA 0
#define BLA 0 // valid
You are allowed to redeclare an identifier in different scopes:
{
int x;
{
double x; // valid
}
}
In the same scope redeclaring an identifier is not valid and at least you'll get a diagnostic:
int x = 0;
double x = 0.0; // not valid
If there are multiple definition of an object in different translation units, it is undefined behavior but the Standard not require a diagnostic so be careful because you may not get any warning.
Upvotes: 1