views:

183

answers:

8

Being a developer born and raised on OO, I was curious to hear how it's possible to avoid global state in a procedural program.

+10  A: 

You can also write object-oriented code in C. You don't get all the C++ goodies and it's ugly, and you have to manually pass the this pointer (I've seen self used for this, in order to make it compatible with C++), but it works. So technically, you don't need global state in pure procedural languages for the very same reasons you don't need it in object-oriented languages. You just have to pass the state around explicitly, rather than implicitly like in OO languages.

OregonGhost
It's not ugly if you do it right. +1 because you're otherwise spot on.
Daniel Stutzbach
I agree; emulation of OO is one way to avoid the problem of global state; but how about a program written in a purely procedural style?
Gurdas Nijor
http://www.jetcafe.org/jim/highlowc.html
Judge Maygarden
+2  A: 

Of course. Just declare a struct somewhere, allocate some memory for it, pass the pointer to the allocated memory to an initialization function, and off you go. Just pass the pointer to all the functions that require using the struct.

Though the question arises as to where you store the pointer to the data you don't want to be global, and then you may end up with a global pointer ;-)

James Morris
A: 

You can have variables on stack or in heap that will exist during all the program life.

Passing object style structure pointers to every function is a good way to have OO C coding style.

(I would suggest to have a look in linux sources)

jag
+2  A: 

All OO is a mindset and a whole bunch of compiler support.

You can achieve much the same by discipline, coding conventions, and passing around structures in most languages.

For example I used to have functions/procedures prefixed with their module identity, taking the first parameter as being the related module struct.

// System.h

typedef struct _System
{
    struct _System *owner;
    LinkedList *elements;
} System;

// System.c

int System_FindName ( System * system, char *name)
{
..
}

etc..

I'd really seriously not like to have to go back to coding like this though. I'm very happy that I haven't had to write and debug a linked list for at least 18 years. It was hard back then without the internet and sitting there isolated in the corner of a cold brightly lit room with green phosphors burning into your retina...

Richard Harrison
In a recent talk, Alan Kay mentioned a program from 1953, which uses pretty much what we would recognize as an "object" today. Obviously, since OO languages weren't invented till 1962, this wasn't written in an OO language. In fact, since the first *programming languages* weren't created till 1957 (ignoring Plankalkül), this wasn't written in any programming language *at all*, it was written in assembler or maybe even machine code. You really *can* write OO in any language.
Jörg W Mittag
+1 from another survivor of the green phosphors and seizure inducing fluorescent lighting.
Tim Post
+4  A: 

As an example, look at how the file I/O functions in the C standard library work with pointer to FILE objects that are (largely) opaque. Or look at how OS APIs deal with handles and such to encapsulate information. A program creates objects, uses APIs that act on those objects adn closes/deletes the objects - all using straight C.

Michael Burr
A: 

You could try, as an example, create with dia (the diagramming tool), a simple class (for example, a square).
http://projects.gnome.org/dia/
http://dia-installer.de/index_en.html

Then, you can transform that class in C code using dia2code:
http://dia2code.sourceforge.net/

Specifically, say you created the class square inside the square.dia diagram. Then, you type:

$ dia2code -t c square.dia

... and you will see that it is possible to convert any object-oriented programming in a C program without global variables. Explore the created files square.c and square.h

NOTE: in Windows, you'll need a workaround in order to make dia2code work. Before using dia2code, change square.dia to square.zip, unzip it, and rename the result as square.dia

Baltasarq
A: 

Simple. Whenever a procedure accesses a global variable, then give this variable as an argument to the procedure instead, either by value or by reference or by pointer, or by whatever your programming language provides. After that there is no more need for the variable to be global.

Secure
+3  A: 

A global variable is nothing but an implicit procedure argument. Make it explicit and the global variable goes away.

Note: the fact that you no longer use a global variable does not mean that you no longer use global state! What we did above was just a purely syntactical transformation, the semantics of the program haven't changed at all. It's just as non-composable, non-modular, non-threadsafe, non-parallelizable as it was before.

Jörg W Mittag
+1 for making the important distinction between syntax (global variable) and semantic (global state).
tristopia