To be honest I don't understand your comment, I think you're talking about something else, so I'll try to rephrase.
My point is that C is not an OOPL. There's two aspects of OOP: 1) the concrete language features 2) a pseudo-philosophical wishy-washy hippie territory where nothing is clear and everything is subjective, where you view all problems as something that is to be modelled with objects, and your own mental model is firmly centred around objects.
Since C lacks concrete OOP features, I will proceed to show why the latter aspect (philosophical OOP) is problematic.
In OOP, objects are entities composed of data and functions that operate on that data. That's what C++ classes usually are: members and methods bound syntactically together. OOP doesn't allow a method to belong to two objects, by definition and by C++ syntax.
Now, let's say you have a C API that offers 2 structs, A and B, and some functions F1A(A, ...), F1B(B, ...), and so on. The people who claim C is OOP language will say "a-ha! A is an object. The data (encapsulated too!) is in type A, and the functions F1A, F2A, ... are the methods. You could write a C++ class 'class A { private: data; public: F1A(...);...};'. Same for B. See? A and B are objects!"
This is the philosophical OOP in action, where "it looks like OOP" becomes "is OOP".
So what happens if the API adds a new function, FAB(A, B, ...), that operates on the internals of A and B? If we switch back to OOP parlance, if you had two classes, A and B, and wanted to add FAB to one of them, which class would FAB belong to?
Well, it's problematic because we're dealing with imaginary objects, so the answer can be whatever you want it to be.
You can arbitrarily say "pick the first parameter type to be the object that owns FAB". Well, what if it's FAB(const char*, A, B)? And even if A is the first one, doesn't FAB changing B break the all-precious object encapsulation? Once you introduce FAB, are these objects at all?
The problem of choosing the "owner" is a common one in C++ OOP because the objects are real (there's syntax to mark something as an object), whereas in C the objects are imaginary and, therefore, a fuzzy ambiguous concept. If you take the set of all functions whose 1st parameter is an int, does that form an object? If everything is an object, is anything an object?
But, like I said, this tends to be a non-problem in C (if you're not a OOP person) because you'll recognise that FAB(A,B) does something useful, and all this conceptual objects design is just noise that does not matter and you're happy to say "my code is not OOP but it does something useful in the best possible way".
Which is why I think that philosophical OOP (object thinking) is dubious, and the only way you can call a language OOP is if it has OOP features. Otherwise, if the only thing you're doing is applying your OOP mindset, I don't think it's fair to say that the language itself is OOP.
My point is that C is not an OOPL. There's two aspects of OOP: 1) the concrete language features 2) a pseudo-philosophical wishy-washy hippie territory where nothing is clear and everything is subjective, where you view all problems as something that is to be modelled with objects, and your own mental model is firmly centred around objects.
Since C lacks concrete OOP features, I will proceed to show why the latter aspect (philosophical OOP) is problematic.
In OOP, objects are entities composed of data and functions that operate on that data. That's what C++ classes usually are: members and methods bound syntactically together. OOP doesn't allow a method to belong to two objects, by definition and by C++ syntax.
Now, let's say you have a C API that offers 2 structs, A and B, and some functions F1A(A, ...), F1B(B, ...), and so on. The people who claim C is OOP language will say "a-ha! A is an object. The data (encapsulated too!) is in type A, and the functions F1A, F2A, ... are the methods. You could write a C++ class 'class A { private: data; public: F1A(...);...};'. Same for B. See? A and B are objects!"
This is the philosophical OOP in action, where "it looks like OOP" becomes "is OOP".
So what happens if the API adds a new function, FAB(A, B, ...), that operates on the internals of A and B? If we switch back to OOP parlance, if you had two classes, A and B, and wanted to add FAB to one of them, which class would FAB belong to?
Well, it's problematic because we're dealing with imaginary objects, so the answer can be whatever you want it to be.
You can arbitrarily say "pick the first parameter type to be the object that owns FAB". Well, what if it's FAB(const char*, A, B)? And even if A is the first one, doesn't FAB changing B break the all-precious object encapsulation? Once you introduce FAB, are these objects at all?
The problem of choosing the "owner" is a common one in C++ OOP because the objects are real (there's syntax to mark something as an object), whereas in C the objects are imaginary and, therefore, a fuzzy ambiguous concept. If you take the set of all functions whose 1st parameter is an int, does that form an object? If everything is an object, is anything an object?
But, like I said, this tends to be a non-problem in C (if you're not a OOP person) because you'll recognise that FAB(A,B) does something useful, and all this conceptual objects design is just noise that does not matter and you're happy to say "my code is not OOP but it does something useful in the best possible way".
Which is why I think that philosophical OOP (object thinking) is dubious, and the only way you can call a language OOP is if it has OOP features. Otherwise, if the only thing you're doing is applying your OOP mindset, I don't think it's fair to say that the language itself is OOP.