Why doesn't ANSI C have namespaces?
Asked Answered
C

10

134

Having namespaces seems like no-brainer for most languages. But as far as I can tell, ANSI C doesn't support it. Why not? Any plans to include it in a future standard?

Concordat answered 9/12, 2010 at 8:14 Comment(8)
Use C++ as C-with-namespace!Tosha
I can of course, but I'd still like to knowConcordat
@Chris Becke What is wrong with C++ namespaces?Tosha
2 things. An unnecessary distinctive syntax: All other languages with namespaces just use '.' as separator as its not ambiguous with other uses of '.'. And, more critically, c++ never introduced a scoped using directive. Which meant that programmers overused using directives to import namespaces into global scope. Which meant that the c++ standards committee now can't add new features to std:: ever as the amount of code that would break as a result has rendered the partitioning redundant.Mellow
@Chris Becke: I like distinctive syntax. I like to know whether I'm looking at a class in a name space or a member in a class.Finecut
I think the folks best qualified to answer this question were/are on an ANSI C committee. Hopefully someone from one of the committees is here. Or ask a mailing list with someone who was, maybe?Elegiac
@ChrisBecke, this is a few years late, but it's interesting that you argue that C++ namespaces were poorly implemented, so they shouldn't be implemented in C. Then you note that other languages implement them without the hangups of C++. If other languages can do it, why not introduce them to C?Leavelle
never use using namespace ... in C++ headers, at least not when you are writing public headers, like for a library ;-)Playacting
W
88

C does have namespaces. One for structure tags, and one for other types. Consider the following definition:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

The first one has tag foo, and the later is made into type foo with a typedef. Still no name-clashing happens. This is because structure tags and types (built-in types and typedef'ed types) live in separate namespaces.

What C doesn't allow is to create new namespace by will. C was standardized before this was deemed important in a language, and adding namespaces would also threaten backwards-compatibility, because it requires name mangling to work right. I think this can be attributed due to technicalities, not philosophy.

EDIT: JeremyP fortunately corrected me and mentioned the namespaces I missed. There are namespaces for labels and for struct/union members as well.

Whitten answered 9/12, 2010 at 8:50 Comment(8)
There are actually more than two name spaces. In addition to the two you mention, there is a name space for labels and name spaces for the members of each struct and union.Finecut
@Finecut : Many thanks for the correction. I only wrote this off memory, I didn't check the standard :-)Whitten
what about namespace for functions?Lammas
@Finecut Do we refer to the namespace of members of a struct foo as "the struct foo namespace"?Consuela
@MinhTran Not normally, but that doesn't alter the fact that each struct has its owen namespace.Finecut
This may well be called namespaces, but I believe these are not the sort of namespaces the OP was asking about.Kilkenny
@Finecut you're obscuring terminology. You can solve similar scoping problems this way but these are namespaces with a lot of extra baggage since these are member objects and variables that belong to an instantiated object. Yes you can use static to get around that but then you're doing just that. Hacking around to mimic namespace behavior.Riven
@Riven Nope. I'm not advocating hacking C features, merely stating the facts. Each struct definition declares a new namespace for its members. I'm not advocating exploiting that fact, nor am I aware of any means of exploiting it since structs cannot have static members.Finecut
A
139

For completeness there are several ways to achieve the "benefits" you might get from namespaces, in C.

One of my favorite methods is using a structure to house a bunch of method pointers which are the interface to your library/etc..

You then use an extern instance of this structure which you initialize inside your library pointing to all your functions. This allows you to keep your names simple in your library without stepping on the clients namespace (other than the extern variable at global scope, 1 variable vs possibly hundreds of methods..)

There is some additional maintenance involved but I feel that it is minimal.

Here is an example:

/* interface.h */

struct library {
    const int some_value;
    void (*method1)(void);
    void (*method2)(int);
    /* ... */
};

extern const struct library Library;
/* end interface.h */

/* interface.c */
#include "interface.h"

void method1(void)
{
   ...
}
void method2(int arg)
{
   ...
}

const struct library Library = {
    .method1 = method1,
    .method2 = method2,
    .some_value = 36
};
/* end interface.c */

/* client code */
#include "interface.h"

int main(void)
{
    Library.method1();
    Library.method2(5);
    printf("%d\n", Library.some_value);
    return 0;
}
/* end client code */

The use of . syntax creates a strong association over the classic Library_function(), Library_some_value method. There are some limitations however, for one you can't use macros as functions.

Ailis answered 16/2, 2015 at 6:19 Comment(11)
... and are compilers smart enough to "dereference" the function pointer at compile time when you do library.method1()?Zaneta
This is so awesome. One thing I might add, I'm trying out making all of my functions in my .c files static by default, thus the only functions exposed are the ones explicitly exposed in the const struct definition in the .c file.Informed
That's a great idea, but how do you deal with constants and enums?Bastien
@Zaneta - sorry to necro, but at least as of version 6.3.0, gcc will compute the actual address of function1/method2 when compiling with both -O2 and -flto. Unless you compile such libraries along with your own source, this approach will add some overhead to its function calls.Permian
@AlexReinking: Well, that's nice, but we would never get these functions inlined. And - necro'ing is great, no apology necessary.Zaneta
I ran your code. In struct definition, function1 should be named method1.Esme
It's adding a lot of overhead.Haymaker
Has Library been initialized when I initialize my own values using Library?Sinless
From my limited C knowledge: Shouldn't the functions be declared static so that they are not global?Uncircumcision
@Zaneta clang is able to inline them godbolt.org/z/4EanMrMrdFike
@OleMorud: Interesting, but modules and namespaces are not quite the same thing.Zaneta
W
88

C does have namespaces. One for structure tags, and one for other types. Consider the following definition:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

The first one has tag foo, and the later is made into type foo with a typedef. Still no name-clashing happens. This is because structure tags and types (built-in types and typedef'ed types) live in separate namespaces.

What C doesn't allow is to create new namespace by will. C was standardized before this was deemed important in a language, and adding namespaces would also threaten backwards-compatibility, because it requires name mangling to work right. I think this can be attributed due to technicalities, not philosophy.

EDIT: JeremyP fortunately corrected me and mentioned the namespaces I missed. There are namespaces for labels and for struct/union members as well.

Whitten answered 9/12, 2010 at 8:50 Comment(8)
There are actually more than two name spaces. In addition to the two you mention, there is a name space for labels and name spaces for the members of each struct and union.Finecut
@Finecut : Many thanks for the correction. I only wrote this off memory, I didn't check the standard :-)Whitten
what about namespace for functions?Lammas
@Finecut Do we refer to the namespace of members of a struct foo as "the struct foo namespace"?Consuela
@MinhTran Not normally, but that doesn't alter the fact that each struct has its owen namespace.Finecut
This may well be called namespaces, but I believe these are not the sort of namespaces the OP was asking about.Kilkenny
@Finecut you're obscuring terminology. You can solve similar scoping problems this way but these are namespaces with a lot of extra baggage since these are member objects and variables that belong to an instantiated object. Yes you can use static to get around that but then you're doing just that. Hacking around to mimic namespace behavior.Riven
@Riven Nope. I'm not advocating hacking C features, merely stating the facts. Each struct definition declares a new namespace for its members. I'm not advocating exploiting that fact, nor am I aware of any means of exploiting it since structs cannot have static members.Finecut
C
24

C has namespaces. The syntax is namespace_name. You can even nest them as in general_specific_name. And if you want to be able to access names without writing out the namespace name every time, include the relevant preprocessor macros in a header file, e.g.

#define myfunction mylib_myfunction

This is a lot cleaner than name mangling and the other atrocities certain languages commit to deliver namespaces.

Cape answered 9/12, 2010 at 14:18 Comment(18)
I see it differently. Complicating the grammar, introducing name mangling on symbols, etc. to achieve something that was already trivial to do with the preprocessor is what I would call a dirty hack and poor design.Cape
I don't see how you can really support that position. Ask the Javascript community about integrating projects when every other system has a different homegrown hack for implementing namespaces. I've never heard anyone complain about the 'namespace' or 'package' keyword adding too much complexity to their language. On the other hand, trying to debug code littered with macros can get hairy fast!Leavelle
I've heard plenty of people complain about C++ name mangling (from standpoints of debugging, toolchain, ABI compatibility, dynamic symbol lookup, ...) and the complexity of not knowing what a particular name is actually referring to.Cape
@R.. That wouldn't happen if the name mangling in C++ were standardised. This alone wouldn't help with the ABI compatibility, but would definitely fix the name mapping problem.Quadrennium
Agreeing that mangling is ugly, but this is far for optimal either. The issue is that you need to maintain a file with a define per public function/variable. So now each source file with a public interface must now comprise three files: the header, the import and the implementation. This solution also does not address the problem of clashing namespaces. Still, with a few adjustments, this is the best solution in the current state of affairs (barring a custom preprocessor). I'd use a reverse domain name as prefix, and macros to choose a prefix to rename to, and to make things terse.Perceptive
Name mangling is ugly when it comes to functions with many inputs. If it were only about namespaces, it would be much less ugly, imho. And your solution works only if you have few functions (unless you want to write hundreds of macros, one per function) and only from the user's perspective. If you use this trick throughout your library, you're only confusing future users, who will see a function named "my_function" without maybe noticing that that's a macro, and the real name of the function is "my_lib_my_function".Kemeny
@bartgol: How is the number of inputs relevant?Cape
@R: well, the mangled names contain strings that denote the name of the type of the input arguments, which could be several. On the other hand, the number of nested namespaces is small (at least in my experience. If I have many, I'm probably doing it wrong). Also, allowing name mangling only for namespaces in C, the last bit of the mangled name would be the function name, making it "not too hard" to read when debugging. Just my opinion on what's ugly and what's "not too ugly". ;)Kemeny
Mangling isn't strictly necessary, just for namespaces. All you need is a separator that is not a valid identifier character. Java does this with the $ and . characters, and nested class names aren't that ugly.Pino
This isn't namespaces, this is using a naming convention to poorly imitate what namespaces give you.Nauseating
I find it mind blowing that C people will actually argue this with a straight face. There are many features in C++ with sharp edges that give people grief. Namespaces are not one of those features. They're great, they work very well. And nothing is trivial with the preprocessor, for the record. Finally, demangling names is trivial, there are plenty of command line utilities that will do it for you.Immigrant
If you can't do using, it's not a namespace. If you can't enclose definitions in namespace foo { /* etc. etc. */ } it's not a namespace.Zaneta
When I started programming I used to use this kind of namespace_name but recommending it as a solution seems silly at best. I think the main issue is that people who provide this kind of solutions didn't actually had the chance to use "real" namespace.Lammas
This is just a silly way to say that the C doesn't have namespaces. With your definition, any language that supports _ in symbols would support namespaces. This isn't the way the term 'namespaces' is usually used in computing.Kilkenny
Your answer may be unclear to a begineer, especially if they do not have a programming background.Irritation
Just want to add that using opens up the possibility for future name overlap issues if the contents of the namespace change, whereas using #define macros lets you explicitly decide which functions to "import".Scepter
Preprocessor is a hack and C programmers should stop denying mistakes they made over 50 years ago. Plenty of languages solved this problem without complicating the grammar. Unlike C which added a whole new DSL and that's somehow "more clean elegant and simple", no it isn't, all it does is bloat compile times and make my eyes bleed whenever I look at it.Equitable
@Equitable 100% agreed. C was a good invention for the time but it is an atrocious programming language. Absolutely no-one on earth should be using it in the 21st century, and the fact that no-one developed a serious contender until Rust came along is a disgraceful shame upon everyone in computing.Martinamartindale
T
16

Historically, C compilers don't mangle names (they do on Windows, but the mangling for the cdecl calling convention consists of only adding an underscore prefix).

This makes it easy to use C libraries from other languages (including assembler) and is one of the reasons why you often see extern "C" wrappers for C++ APIs.

Trammell answered 9/12, 2010 at 10:44 Comment(2)
But why is that such a problem? I mean, suppose all namespaced names would begin with _da13cd6447244ab9a30027d3d0a08903 and then the name (That's a UUID v4 I just generated) ? There is a chance this might break names which use this particular UUID, but that chance is essentially zero. So there will in practice not be a problem mangling only_namespace_names.Zaneta
@Zaneta it isn't. Lazy programmers is the only problem here. Name mangling being absolute garbage just like its implementation is a sign of such lazyness. Too bad, when they could've easily been lazy by mangling properly. Imagine if "name mangling", instead of an excuse, was an actual feature, and a function add in a module vector of a library myvectors resulted in a symbol myvectors_vector_add and that's what everyone consuming the C library would be using universally without problems while in C it would just be vector::add or equivalent. I can't imagine either.Equitable
R
9

just historical reasons. nobody thought of having something like a namespace at that time. Also they were really trying to keep the language simple. They may have it in the future

Rhapsodic answered 9/12, 2010 at 8:26 Comment(2)
Is there any movement in the standard committee to add namespaces to C in the future? Possible with the move to C/C++ module this could make it easier in the future?Insulation
@Insulation There is no will to add namespaces to C because of backward compatibility reasons.Lammas
T
7

Not an answer, but not a comment. C doesn't provide a way to define namespace explicitly. It has variable scope. For example:

int i=10;

struct ex {
  int i;
}

void foo() {
  int i=0;
}

void bar() {
  int i=5;
  foo();
  printf("my i=%d\n", i);
}

void foobar() {
  foo();
  bar();
  printf("my i=%d\n", i);
}

You can use qualified names for variables and functions:

mylib.h

void mylib_init();
void mylib_sayhello();

The only difference from namespaces it that you cannot be using and cannot import from mylib.

Teniers answered 9/12, 2010 at 8:41 Comment(1)
You can also not replace the last two lines with namespace mylib { void init(); void say_hello(); } which is also important(ish).Zaneta
G
6

ANSI C was invented before namespaces were.

Galatea answered 9/12, 2010 at 8:30 Comment(4)
It was? The first ANSI C spec was 1989. I'm pretty sure that namespaces (in some form or another) were in programming languages before then. Ada, for example, was standardized in 1983 and had packages as namespaces. Those in turn were essentially based on Modula-2 modules.Silverweed
I wouldn't date the invention of ANSI C to when its spec was officially adopted; the language existed beforehand, and the spec just documented what was already there. Although from some of the answers on this site one might think the spec came first and the first compiler as an afterthought.Galatea
ANSI C did have some significant differences from pre-ANSI C, but namespaces weren't one of them.Putman
Meanwhile, I am writing it in 2020, well after namespaces came into existence. The latest C standards still do not have them. As much as C makes sense, this is one feature that is missing sorely.Marijuana
Z
2

Because people who want to add this capability to C have not gotten together and organized to put some pressure on compiler author teams and on ISO bodies.

Zaneta answered 1/10, 2015 at 11:44 Comment(2)
I think we will see namespace in C is only if these people would organise themselves and create an extension(s) with namespace support. Then the ISO bodies will have no choice but bring publish them as standard(with more or less changes). That's how javascript(which has some similarities with C in this respect) did it.Lammas
@themihai: "create an extension" = get the gcc and clang people to compile namespaces.Zaneta
B
2

C doesn't support namespaces like C++. The implementation of C++ namespaces mangle the names. The approach outlined below allows you to get the benefit of namespaces in C++ while having names that are not mangled. I realize that the nature of the question is why doesn't C support namespaces (and a trivial answer would be that it doesn't because it wasn't implemented :)). I just thought that it might help someone to see how I've implemented the functionality of templates and namespaces.

I wrote up a tutorial on how to get the advantage of namespaces and/or templates using C.

Namespaces and templates in C

Namespaces and templates in C (using Linked Lists)

For the basic namespace, one can simply prefix the namespace name as a convention.

namespace MY_OBJECT {
  struct HANDLE;
  HANDLE *init();
  void destroy(HANDLE * & h);

  void do_something(HANDLE *h, ... );
}

can be written as

struct MY_OBJECT_HANDLE;
struct MY_OBJECT_HANDLE *my_object_init();
void my_object_destroy( MY_OBJECT_HANDLE * & h );

void my_object_do_something(MY_OBJECT_HANDLE *h, ... );

A second approach that I have needed that uses the concept of namespacing and templates is to use the macro concatenation and include. For example, I can create a

template<T> T multiply<T>( T x, T y ) { return x*y }

using template files as follows

multiply-template.h

_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y);

multiply-template.c

_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y) {
  return x*y;
}

We can now define int_multiply as follows. In this example, I'll create a int_multiply.h/.c file.

int_multiply.h

#ifndef _INT_MULTIPLY_H
#define _INT_MULTIPLY_H

#ifdef _multiply_
#undef _multiply_
#endif
#define _multiply_(NAME) int ## _ ## NAME 

#ifdef _multiply_type_
#undef _multiply_type_
#endif
#define _multiply_type_ int 

#include "multiply-template.h" 
#endif

int_multiply.c

#include "int_multiply.h"
#include "multiply-template.c"

At the end of all of this, you will have a function and header file for.

int int_multiply( int x, int y ) { return x * y }

I created a much more detailed tutorial on the links provided which show how it works with linked lists. Hopefully this helps someone!

Brinna answered 29/12, 2017 at 21:51 Comment(2)
Your links explain how to add namespaces. However, the question was why namespaces are not supported. So this answer is not an answer and should be a comment instead.Cubature
@ThomasWeller You're right, but I really can't see how all of that information could fit into a comment. For me, it is valuable as it is, and it would lose its meaning by shortening it to a comment.Foghorn
B
2

You can. Like other's answer, define function pointers in a struct.

However, declare it in your header file, mark it static const and initialize it with the corresponding functions. With -O1 or higher it will be optimized as normal function calls

eg:

void myfunc(void);
    
static const struct {
      void(*myfunc)(void);
} mylib = {
      .myfunc = myfunc
};

Take advantage of the #include statement so you do not need to define all functions in one single header.

Do not add header guards as you are including it more than once.

eg: header1.h

#ifdef LIB_FUNC_DECL
void func1(void);
#elif defined(LIB_STRUCT_DECL)
struct {
      void(*func)(void);
} submodule1;
#else
    .submodule1.func = func1,
#endif

mylib.h

#define LIB_FUNC_DECL
#include "header1.h"
#undef LIB_FUNC_DECL
#define LIB_STRUCT_DECL

static const struct {
#include "header1.h"
#undef LIB_STRUCT_DECL
} mylib = {
    #include "header1.h"
};
Bicyclic answered 17/12, 2021 at 11:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.