Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

It seems that C has its own quasi-objects such as 'structs' that can be considered as objects (in the high-level way that we would normally think).

And also, C files themselves are basically separate "modules", right? Then aren't modules kind of like 'objects' too? I'm confused as to why C, which seems so similar to C++, is considered a low-level "procedural" language where as C++ is high-level "object-oriented"

*edit: (clarification) why and where, is the line drawn, for what an 'object' is, and isn't?

share|improve this question
33  
All - why the down votes? It's a basic question but not a bad one. –  Jon Hopkins Oct 10 '11 at 20:59
7  
You can use OO principles effectively in C (and people who write good C code typically do), but the language is not built around making it easy, as many more recent languages are. –  asveikau Oct 10 '11 at 22:47
5  
C simply has a different, simpler, and (to be honest) better defined (at least among the open-source community) approach to data abstraction. C++ tends to be an abstraction powerhouse and allows for many great things, but comes with a cost of having to understand how to [not] use them properly, which is, more often than not, quite missing in common programs. See my full answer for more details. –  Yam Marcovic Oct 10 '11 at 23:55
1  
Shortly: Structs can't have methods. (Pointer to a function doesn't quite cut it). –  SF. Oct 11 '11 at 7:01
1  
It is possible to do object-based programming in C, with some difficulty. But that doesn't make it object oriented. –  Wedge Oct 11 '11 at 9:24

11 Answers 11

up vote 83 down vote accepted

It seems that C has its own quasi-objects such as 'structs' that can be considered as objects

Let's together you and I read through the Wikipedia page on object oriented programming and check off the features of C-style structs that correspond to what is traditionally considered to be object-oriented style:

(OOP) is a programming paradigm using "objects" – data structures consisting of data fields and methods together with their interactions

Do C structs consist of fields and methods together with their interactions? No.

Programming techniques may include features such as data abstraction, encapsulation, messaging, modularity, polymorphism, and inheritance.

Do C structs do any of these things in a "first class" way? No. The language works against you every step of the way.

the object-oriented approach encourages the programmer to place data where it is not directly accessible by the rest of the program

Do C structs do this? No.

An object-oriented program will usually contain different types of objects, each type corresponding to a particular kind of complex data to be managed or perhaps to a real-world object or concept

Do C structs do this? Yes.

Objects can be thought of as wrapping their data within a set of functions designed to ensure that the data are used appropriately

No.

each object is capable of receiving messages, processing data, and sending messages to other objects

Can a struct itself send and receive messages? No. Can it process data? No.

OOP data structures tend to "carry their own operators around with them"

Does this happen in C? No.

Dynamic dispatch ... Encapsulation ... Subtype polymorphism ... Object inheritance ... Open recursion ... Classes of objects ... Instances of classes ... Methods which act on the attached objects ... Message passing ... Abstraction

Are any of these features of C structs? No.

Precisely which characteristics of structs do you think are "object oriented"? Because I can't find any other than the fact that structs define types.

Now, of course you can make structs that have fields that are pointers to functions. You can make structs have fields that are pointers to arrays of function pointers, corresponding to virtual method tables. And so on. You can of course emulate C++ in C. But that is a very non-idiomatic way to program in C; you'd be better off just using C++.

And also, C files themselves are basically separate "modules", right? Then aren't modules kind of like 'objects' too?

Again, what characteristics of modules are you thinking of that makes them act like objects? Do modules support abstraction, encapsulation, messaging, modularity, polymorphism, and inheritance?

Abstraction and encapsulation are pretty weak. Obviously modules are modular; that's why they're called modules. Messaging? Only in the sense that a method call is a message and modules can contain methods. Polymorphism? Nope. Inheritance? Nope. Modules are pretty weak candidates for "objects".

share|improve this answer
13  
I disagree that "emulating C++" (your term) isn't idiomatic C. One counter example would be how an OS kernel typically implements file operations - take Linux as an example, where you have structs full of function pointers. They may be somewhat "domain-specific" idioms (restricted to writing drivers on *nix, say), but they are recognizable and do the job cleanly enough for some purposes. There are also some examples of user mode libraries that do some notion of OO well enough; take Gtk+ and the libraries it depends on. Call it hacky and you may be right, but these are not terrible to work with –  asveikau Oct 10 '11 at 23:16
4  
@asveikau: Doesn't the idea that a practice is unusual (even if not unheard of) and "hacky" mean that it is, by definition, not idiomatic? –  Adam Robinson Oct 11 '11 at 1:50
15  
@asveikau: Sure, there are things you can do to make C programs more OO in style. But as you say, it requires discipline to do so; the language features themselves do not naturally lead you towards encapsulation, polymorphism, class inheritance, and so on. Rather, the developer can impose that pattern on the language. That doesn't mean that structs are logically the same thing as objects. Heck, you can program in an OO style in Lisp too, but that doesn't mean that cons cells are objects. –  Eric Lippert Oct 11 '11 at 5:48
3  
@asveikau, may I suggest that your (mis)interpretation of "idiom" as "of one's own" is mildly... idiosyncratic? :) –  Benjol Oct 11 '11 at 5:57
6  
@BillK: Structs cannot contain code in C. Structs can contain function pointers, which are data. Function pointers aren't code. Code is a textual artifact created by a programmer. –  Eric Lippert Oct 11 '11 at 21:36

There are a number of key ingredients to OO, but the big ones are that the majority of code does not know what is inside an object (they see the surface interface, not the implementation), that the state of an object is a managed unit (i.e., when the object ceases to be, so does its state), and when some code invokes an operation on an object, they do so without knowing exactly what that operation is or involves (all they do is follow a pattern to throw a “message” over the wall).

C does encapsulation just fine; code which does not see the definition of a structure can't (legitimately) peek inside it. All you need to do that is to put a definition like this in a header file:

struct FooImpl;
typedef struct FooImpl *Foo;

Of course, there will be a need for a function that builds Foos (i.e., a factory) and that should delegate some of the work to the allocated object itself (i.e., through a “constructor” method), and also to have a way of disposing of the object again (while letting it clean up via its “destructor” method) but that's details.

Method dispatch (i.e., messaging) can also be done through the convention that the first element of the structure is actually a pointer to a structure full of function pointers, and that each of those function pointers must take a Foo as its first argument. Dispatch then becomes a matter of looking up the function and calling it with the right argument rewrite, which isn't that hard to do with a macro and a little cunning. (That table of functions is the core of what a class really is in a language like C++.)

Furthermore, that gives you late binding too: all the dispatch code knows is that it is invoking a particular offset into a table pointed at by the object. That only needs to be set during the allocation and initialization of the object. It's possible to go with even more complex dispatch schemes that buy you more runtime dynamism (at a cost of speed) but they're cherries on top of the basic mechanism.

Yet that doesn't mean that C is an OO language. The key is that C leaves you to do all the tricky work of writing the conventions and dispatch mechanism yourself (or use a third-party library). That's a lot of work. It also doesn't provide syntactic or semantic support, so implementing a full class system (with things like inheritance) would be unnecessarily painful; if you're dealing with a complex problem that is well described by an OO model, an OO language will be very useful in writing the solution. The extra complexity can be justified.

share|improve this answer

Not a bad question.

If you are going to call c an OO language you would need to called just about all procedural languages OO too. So it would make the term meaningless. c has no language support for OO. If has structs, but structs are types no classes.

Actually c doesn't have a lot of features at all compared to most languages. It's mostly use for it's speed, simplicity, popularity and support including tons of libraries.

share|improve this answer

You need to look at the other side of the coin: C++.

In OOP, we think of an abstract object (and design the program accordingly), for example a car that can stop, accelerate, turn left or right, etc. A struct with a bundle of functions simply does not fit the concept.

With "real" objects we need to hide the members for instance, or we can also have inheritance with a real "is a" relationship and many more.

AFTER READING THE COMMENTS BELOW: Well it's right that (almost) everything can be done with C (that is always true), but at first glance I thought that what separates c from c++ is the way you think when designing a program.

The only thing that really makes the difference is the imposing of policies by the compiler. i.e pure virtual function, and such. but this answer will only relate to technical issues, but I think the the main difference (as mentioned) is the original way you think while you code, since C++ gives you a better built in syntax for doing such things, instead of doing OOP in a somewhat clumsy way in C.

share|improve this answer
    
Not really sure why a struct with a "bundle of functions" doesn't fit the concept? +1 for the answer though –  Dark Templar Oct 10 '11 at 20:55
1  
Aside from access control (private/protected/public) everything else can be done with structs. –  Coder Oct 10 '11 at 20:58
1  
@DarkTemplar: Well, you can try to emulate OOP in C (people have actually written ebooks on that topic and do it in the real world, albeit very rarely), like you can try emulating functional programming in Java. But C provides zero help for it, hence C the language isn't object-oriented. –  delnan Oct 10 '11 at 20:58

Let's just look at the definition of OO:

  • Messaging
  • Encapsulation
  • Late Binding

C provides none of those three. In particular, it doesn't provide Messaging, which is the most important one.

share|improve this answer
1  
I think I'd have to disagree with that. You can most certainly have messaging in C — work with Objective C APIs from C and you find that out in depth — and late binding can be done through function pointers, but you don't get lots of syntactic sugar to hide it. (Encapsulation is actually easy in C; pointers to incomplete structure types do the job perfectly.) –  Donal Fellows Oct 11 '11 at 8:03
    
Inheritance is also considered important in OO, and C doesn't do that. The closest thing to encapsulation in C is separate files that can have internal (static) functions and data members. –  David Thornley Oct 11 '11 at 13:39
    
@DonalFellows, the actual message passing in Objective-C could be easily implemented as a C99 macro. The only thing that the compiler has going for it is that it generates all the necessary structures statically from a few lines of high level code. Most if not all features are available from the C API. –  qpr Oct 11 '11 at 15:22

Object Oriented refers to both an architectural pattern (or even a meta-pattern), and, the languages that have features to help implement or mandate using this pattern.

You can implement an "OO" design (Gnome desktop is perhaps the best example of OO done in pure C), I have even seen this done with COBOL!

However being able to implement an OO design dose not make the language OO. Purists would argue that Java and C++ are not truly OO as you cannot override or inherit the basic "types" such as "int" and "char", and, Java does not support multiple inheritance. But as they are the most widely used OO languages and support most of the paradigm most "real" programmers who get paid to produce working code regard them as the OO languages.

C on the other hand supports only structures (as do COBOL,Pascal and dozens of other procedural languages), you could argue that supports multiple inheritance in that you can use any function on any piece of data but most would regards this as a bug rather than a feature.

share|improve this answer

C, just like C++, has the capability of providing Data Abstraction, which is one idiom of the object-oriented-programming paradigm that existed before it.

  • C structs can have data (and that's their main purpose)
  • C structs can also define function pointers as data
  • C structs can and often have a set of functions associated with them, just like methods, only the this pointer is not passed implicitly, but you must specify it explicitly as the first argument to each method designed to handle the specified struct. C++ does this automatically for you, both when you define and call class/struct methods.

OOP in C++ extends the means to abstract data. Some say it's harmful, while others consider it a good tool when used correctly.

  • C++ makes the this pointer implicit by not requiring the user to pass it into "methods of the class/struct" as long as the type can be (at least partly) identified.
  • C++ lets you restrict access to certain methods (class functions), and hence allows for more "defensive programming" or "idiot-proofing".
  • C++ encourages abstractions by providing stronger type-safety by introducing
    1. The new operator instead of malloc + cast
    2. Templates instead of void pointers
    3. Inline functions receiving typed-values instead of macros
    4. Built in Polymorphism which you don't have to implement yourself, that lets you create abstraction hierarchies, contracts and specializations.

However, you'll find many C "hackers" preaching for how C is perfectly capable of just the right amount of abstraction and how the overhead created by C++ only distracts them from solving the actual problem.

Inefficient abstracted programming models where two years down the road you notice that some abstraction wasn't very efficient, but now all your code depends on all the nice object models around it, and you cannot fix it without rewriting your app. -- Linus Torvalds

Others tend to look at it in a more balanced way, accepting both the advantages along with the disadvantages.

C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off. -- Bjarne Stroustrup

share|improve this answer

You kind of said it yourself. While C has things that are kind of like objects, they are still not objects, and that is why C is not considered an OOP language.

share|improve this answer
1  
Well, I guess the question is: why and where is the line drawn for what is an object and what isn't? –  Dark Templar Oct 10 '11 at 20:49

The key word is "oriented", not "object". Even C++ code that uses objects but uses them like structs is not object oriented.

C and C++ can both do OOP (aside from no access control in C), but the syntax for doing it in C is inconvenient (to say the least), while the syntax in C++ makes it very inviting. C is oriented to procedural, while C++ is oriented to objects, despite nearly identical core capabilities in that regard.

Code that uses objects to implement designs that can only be done with objects (usually meaning taking advantage of polymorphism) is object oriented code. Code that uses objects as little more than bags of data, even using inheritance in an object oriented language, is really just procedural code that is more complicated than it needs to be. Code in C that uses function pointers that are changed around at runtime with structs full of data is kinda doing polymorphism, and could be said to be "object oriented", even in a procedurally oriented language.

share|improve this answer
2  
+1 For pointing our C can be OO. It's not convenient, but it can be done. –  dietbuddha Oct 11 '11 at 4:04
    
It's easer to create objects in VBA, but I wouldn't consider it object 'oriented' either. –  JeffO Oct 11 '11 at 12:09
    
VBA I call "object based". It uses objects, but not polymorphically, and in the little bit of work I've done in it, I'm not sure you can even do polymorphism no matter what kind of code acrobatics you try. It's basically a procedural language with encapsulation. –  kylben Oct 11 '11 at 12:17
2  
Most languages can act as an OO, functional or pretty much any style of language. the difference is the "Oriented" and I'd never heard it put that way before. I wish I could vote this up 3 times and accept it, it's the right answer. –  Bill K Oct 11 '11 at 15:34
1  
@kylben It wouldn't be too much of a stretch to store SQL code in the table then extract and execute (making the table your object) It would be an interesting experiment. Actually it's a little tempting... –  Bill K Oct 11 '11 at 20:07

Based on the very highest level principals:

An object is an encapsulation of data and behaviour in an interlinked way such that they operate as a whole that can be instantiate multiple times and worked on as a black box if you know the external interface.

Structs contain data but no behaviour and therefore can not be considered objects.

Modules contain both behaviour and data but are not encapsulated in such a way that the two are related and certainly can't be instantiated multiple times.

And that's before you get onto inheritance and polymorphism...

share|improve this answer
    
How come behavior and data in modules aren't related? Aren't member functions basically the 'behavior' on the data that exist inside the module? –  Dark Templar Oct 10 '11 at 21:05
4  
The problem is that they are not encapsulated, not that they are not related. –  Eoin Carroll Oct 10 '11 at 21:08
    
Actually objects are centred principally around behaviour, not data. Data is/should be a second class citizen in OOP. Structs, instead are centred around data and have no behaviour. –  Sklivvz Oct 11 '11 at 0:27
1  
@Dark Templar - What Eoin said... It's in the nature of the relationship. I can see where you're coming from - you could certainly use Structs within a module in such a way that it emulated some very very basic elements of OO but much of what you'd be doing would rely on the programmer sticking to a set of self imposed rules rather than having the language enforce it. And why would you bother? You're getting none of the benefits of OO - no inheritance for instance - and you're restricting yourself. –  Jon Hopkins Oct 11 '11 at 6:20
    
This is a better answer than the one marked correct. –  zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz Nov 2 '11 at 18:34

"structs" are data only. The usual quick and dirty test of "object orientation" is: "Is there a structure that allows code and data to be encapsulated as a single unit?". C fails that, and is hence procedural. C++ passes that test.

share|improve this answer
6  
There are workarounds, structs can have static function pointers to member functions. They will need explicit this pointer, but in that case, data and means to process data will be encapsulated inside the structure. –  Coder Oct 10 '11 at 20:50
    
@Brian Knoblauch: but isn't a C file itself an encapsulation of data and code?? –  Dark Templar Oct 10 '11 at 20:51
    
@DarkTemplar In a sense, yes, but unless you manage to create translation units, compile them and load them into the running process at runtime, this does you little good. –  delnan Oct 10 '11 at 20:53
    
translation units? >.< –  Dark Templar Oct 10 '11 at 20:56
    
@Dark Templar: A translation unit is a source file plus anything #included into it, and minus anything removed by not being conditionally included (#if, #ifdef, and the like). –  David Thornley Oct 11 '11 at 13:45

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.