why can't we declare functions inside a structure? - c

I read plenty of questions regarding
declaration of functions inside structure?
But I did not get a satisfactory answer.
My question is not about whether functions can be declared inside a structure or not?
Instead, my question is
WHY function can not be declared inside structure?

Well that is the fundamental difference between C and C++ (works in C++). C++ supports classes (and in C++ a struct is a special case of a class), and C does not.
In C you would implement the class as a structure with functions that take a this pointer explicitly, which is essentially what C++ does under the hood. Coupled with a sensible naming convention so you know what functions belong to which classes (again something C++ does under then hood with name-mangling), you get close to object-based if not object-oriented programming. For example:
typedef struct temp
{
int a;
} classTemp ;
void classTemp_GetData( classTemp* pThis )
{
printf( "Enter value of a : " );
scanf( "%d", &(pThis->a) );
}
classTemp T ;
int main()
{
classTemp_GetData( &T );
}
However, as you can see without language support for classes, implementing then can become tiresome.
In C, the functions and data structures are more or less bare; the language gives a minimum of support for combining data structures together, and none at all (directly) for including functions with those data structures.
The purpose of C is to have a language that translates as directly as possible into machine code, more like a portable assembly language than a higher-level language such as C++ (not that C++ is all that high-level). C let's you get very close to the machine, getting into details that most languages abstract away; the down side of this is that you have to get close to the machine in C to use the language to its utmost. It takes a completely different approach to programming from C++, something that the surface similarities between them hide.
Check out here for more info (wonderful discussions there).
P.S.: You can also accomplish the functionality by using function pointers, i.e.
have a pointer to a function (as a variable) inside the struct.
For example:
#include <stdio.h>
struct t {
int a;
void (*fun) (int * a); // <-- function pointers
} ;
void get_a (int * a) {
printf (" input : ");
scanf ("%d", a);
}
int main () {
struct t test;
test.a = 0;
printf ("a (before): %d\n", test.a);
test.fun = get_a;
test.fun(&test.a);
printf ("a (after ): %d\n", test.a);
return 0;
}

WHY function can not be declared inside structure?
Because C standard does not allow to declare function/method inside a structure. C is not object-oriented language.
6.7.2.1 Structure and union specifiers:
A structure or union shall not contain a member with incomplete or function type(hence,
a structure shall not contain an instance of itself, but may contain a pointer to an instance
of itself), except that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union containing, possibly
recursively, a member that is such a structure) shall not be a member of a structure or an
element of an array.

I suppose there were and are many reasons, here are several of them:
C programming language was created in 1972, and was influenced by pure assembly language, so struct was supposed as "data-only" element
As soon as C is NOT object oriented language - there is actually no sense to define functions inside "data structure", there are no such entity as constructor/method etc
Functions are directly translated to pure assembly push and call instructions and there are no hidden arguments like this

I guess, because it wouldn't make much sence in C. If you declare a function inside structure, you expect it to be somehow related to that structure, right? Say,
struct A {
int foo;
void hello() {
// smth
}
}
Would you expect hello() to have access to foo at least? Because otherwise hello() only got something like namespace, so to call it we would write A.hello() - it would be a static function, in terms of C++ - not much difference from normal C function.
If hello() has access to foo, there must be a this pointer to implement such access, which in C++ always implicitly passed to functions as first argument.
If a structure function has access to structure variables, it must be different somehow from access that have other functions, again, to add some sence to functions inside structures at all. So we have public, private modificators.
Next. You don't have inheritance in C (but you can simulate it), and this is something that adds lots of sence to declaring functions inside structutes. So here we'd like to add virtual and protected.
Now you can add namespaces and classes, and here you are, invented C++ (well, without templates).
But C++ is object-oriented, and C is not. First, people created C, then they wrote tons of programs, understood some improvements that could be made, and then, following reasonings that I mentioned earlier, they came up with C++. They did not change C instead to separate concepts - C is procedure-oriented, and C++ is object-oriented.

C was designed so that it could be processed with a relatively simple compilation system. To allow function definitions to appear within anything else would have required the compiler to keep track of the context in which the function appeared while processing it. Given that members of a structure, union, or enum declaration do not enter scope until the end of the declaration, there would be nothing that a function declared within a structure could do which a function declared elsewhere could not.
Conceptually, it might have been nice to allow constant declarations within a structure; a constant pointer to a literal function would then be a special case of that (even if the function itself had to be declared elsewhere), but that would have required the C compiler to keep track of more information for each structure member--not just its type and its offset, but also whether it was a constant and, if so, what its value should be. Such a thing would not be difficult in today's compilation environments, but early C compilers were expected to run with orders of magnitude less memory than would be available today.
Given that C has been extended to offer many features which could not very well be handled by a compiler running on a 64K (or smaller) system, it might reasonably be argued that it should no longer be bound by such constraints. Indeed, there are some aspect of C's heritage which I would like to lose, such as the integer-promotion rules which require even new integer types to follow the inconsistent rules for old types, rather than allowing the new types to have explicitly specified behavior [e.g. have a wrap32_t which could be converted to any other integer type without a typecast, but when added to any "non-wrap" integer type of any size would yield a wrap32_t]. Being able to define functions within a struct might be nice, but it would be pretty far down on my list of improvements.

Related

Providing helper functions when rolling out own structures

if I am developing a C shared library and I have my own structs. To make common operations on these struct instances easier for library consumers, can I provide function pointers to such functions inside the struct itself? Is it a good practice? Would there be issues with respect to multithreading where a utility function is called in parallel with different arguments and so on?
I know it goes a lot closer to C++ classes but I wish to stick to C and learn how it would be done in a procedural language as opposed to OOP.
To give an example
typedef struct tag tag;
typedef struct my_custom_struct my_custom_struct;
struct tag
{
// ...
};
struct my_custom_struct
{
tag *tags;
my_custom_struct* (*add_tag)(my_custom_struct* str, tag *tag);
};
my_custom_struct* add_tag(my_custom_struct* str, tag *tag)
{
// ...
}
where add_tag is a helper that manages to add the tag to tag list inside *str.
I saw this pattern in libjson-c like here- http://json-c.github.io/json-c/json-c-0.13.1/doc/html/structarray__list.html. There is a function pointer given inside array_list to help free it.
To make common operations on these struct instances easier for library
consumers, can I provide function pointers to such functions inside
the struct itself?
It is possible to endow your structures with members that are function pointers, pointing to function types whose parameters include pointers to your structure type, and that are intended to be used more or less like C++ instance methods, more or less as presented in the question.
Is it a good practice?
TL;DR: no.
The first problem you will run into is getting those pointer members initialized appropriately. Name correspondence notwithstanding, the function pointers in instances of your structure will not automatically be initialized to point to a particular function. Unless you make the structure type opaque, users can (and undoubtedly sometimes will) declare instances without calling whatever constructor-analog function you provide for the purpose, and then chaos will ensue.
If you do make the structure opaque (which after all isn't a bad idea), then you'll need non-member functions anyway, because your users won't be able to access the function pointers directly. Perhaps something like this:
struct my_custom_struct *my_add_tag(struct my_custom_struct *str, tag *tag) {
return str->add_tag(str, tag);
}
But if you're going to provide for that, then what's the point of the extra level of indirection? (Answer: the only good reason for that would be that in different instances, the function pointer can point to different functions.)
And similar applies if you don't make the structure opaque. Then you might suppose that users would (more) directly call
str->add_tag(str, tag);
but what exactly makes that a convenience with respect to simply
add_tag(str, tag);
?
So overall, no, I would not consider this approach a good practice in general. There are limited circumstances where it may make sense to do something along these lines, but not as a general library convention.
Would there be issues with
respect to multithreading where a utility function is called in
parallel with different arguments and so on?
Not more so than with functions designated any other way, except if the function pointers themselves are being modified.
I know it goes a lot closer to C++ classes but I wish to stick to C
and learn how it would be done in a procedural language as opposed to
OOP.
If you want to learn C idioms and conventions then by all means do so. What you are describing is not one. C code and libraries can absolutely be designed with use of OO principles such as encapsulation, and to some extent even polymorphism, but it is not conventionally achieved via the mechanism you describe. This answer touches on some of the approaches that are used for the purpose.
Is it a good practice?
TLDR; no.
Background:
I've been programming almost exclusively in embedded C on STM32 microcontrollers for the last year and a half (as opposed to using C++ or "C+", as I'll describe below). It's been very insightful for me to have to learn C at the architectural level, like I have. I've studied C architecture pretty hard to get to where I can say I "know C". It turns out, as we all know, C and C++ are NOT the same language. At the syntax level, C is almost exactly a subset of C++ (with some key differences where C supports stuff C++ does not), hence why people (myself included before this) frequently think/thought they are pretty much the same language, but at the architectural level they are VASTLY DIFFERENT ANIMALS.
Aside:
Note that my favorite approach to embedded is to use what some colloquially know as "C+". It is basically using a C++ compiler to write C-style embedded code. You basically just write C how you'd expect to write C, except you use C++ classes to vastly simplify the (otherwise pure C) architecture. In other words, "C+" is a pseudonym used to describe using a C++ compiler to write C-like code that uses classes instead of "object-based C" architecture (which is described below). You may also use some advanced C++ concepts on occasion, like operator overloading or templates, but avoid the STL for the most part to not accidentally use dynamic allocation (behind-the-scenes and automatically, like C++ vectors do, for example) after initialization, since dynamic memory allocation/deallocation in normal run-time can quickly use up scarce RAM resources and make otherwise-deterministic code non-deterministic. So-called "C+" may also include using a mix of C (compiled with the C compiler) and C++ (compiled with the C++ compiler), linked together as required (don't forget your extern "C" usage in C header files included in your C++ code, as required).
The core Arduino source code (again, the core, not necessarily their example "sketches" or example code for beginners) does this really well, and can be used as a model of good "C+" design. <== before you attack me on this, go study the Arduino source code for dozen of hours like I have [again, NOT the example "sketches", but their actual source code, linked-to below], and drop your "arduino is for beginners" pride right now.
The AVR core (mix of C and "C+"-style C++) is here: https://github.com/arduino/ArduinoCore-avr/tree/master/cores/arduino
Some of the core libraries ("C+"-style C++) are here: https://github.com/arduino/ArduinoCore-avr/tree/master/libraries
[aside over]
Architectural C notes:
So, regarding C architecture (ie: actual C, NOT "C+"/C-style C++):
C is not an OO language, as you know, but it can be written in an "object-based" style. Notice I say "object-based", NOT "object oriented", as that's how I've heard other pedantic C programmers refer to it. I can say I write object-based C architecture, and it's actually quite interesting.
To make object-based C architecture, here's a few things to remember:
Namespaces can be done in C simply by prepending your namespace name and an underscore in front of something. That's all a namespace really is after-all. Ex: mylibraryname_foo(), mylibraryname_bar(), etc. Apply this to enums, for example, since C doesn't have "enum classes" like C++. Apply it to all C class "methods" too since C doesn't have classes. Apply to all global variables or defines as well that pertain to a particular library.
When making C "classes", you have 2 major architectural options, both of which are very valid and widely used:
Use public structs (possibly hidden in headers named "myheader_private.h" to give them a pseudo-sense of privacy)
Use opaque structs (frequently called "opaque pointers" since they are pointers to opaque structs)
When making C "classes", you have the option of wrapping up pointers to functions inside of your structs above to give it a more "C++" type feel. This is somewhat common, but in my opinion a horrible idea which makes the code nearly impossible to follow and very difficult to read, understand, and maintain.
1st option, public structs:
Make a header file with a struct definition which contains all your "class data". I recommend you do NOT include pointers to functions (will discuss later). This essentially gives you the equivalent of a "C++ class where all members are public." The downside is you don't get data hiding. The upside is you can use static memory allocation of all of your C "class objects" since your user code which includes these library headers knows the full specification and size of the struct.
2nd option: opaque structs:
In your library header file, make a forward declaration to a struct:
/// Opaque pointer (handle) to C-style "object" of "class" type mylibrarymodule:
typedef struct mylibrarymodule_s *mylibrarymodule_h;
In your library .c source file, provide the full definition of the struct mylibrarymodule_s. Since users of this library include only the header file, they do NOT get to see the full implementation or size of this opaque struct. That is what "opaque" means: "hidden". It is obfuscated, or hidden away. This essentially gives you the equivalent of a "C++ class where all members are private." The upside is you get true data hiding. The downside is you can NOT use static memory allocation for any of your C "class objects" in your user code using this library, since any user code including this library doesn't even know how big the struct is, so it cannot be statically allocated. Instead, the library must do dynamic memory allocation at program initialization, one time, which is safe even for embedded deterministic real-time safety-critical systems since you are not allocating or freeing memory during normal program execution.
For a detailed and full example of Option 2 (don't be confused: I call it "Option 1.5" in my answer linked-to here) see my other answer on opaque structs/pointers here: Opaque C structs: how should they be declared?.
Personally, I think the Option 1, with static memory allocation and "all public members", may be my preferred approach, but I am most familiar with the opaque struct Option 2 approach, since that's what the C code base I work in the most uses.
Bullet 3 above: including pointers to functions in your structs.
This can be done, and some do it, but I really hate it. Don't do it. It just makes your code so stinking hard to follow. In Eclipse, for instance, which has an excellent indexer, I can Ctrl + click on anything and it will jump to its definition. What if I want to see the implementation of a function I'm calling on a C "object"? I Ctrl + click it and it jumps to the declaration of the pointer to the function. But where's the function??? I don't know! It might take me 10 minutes of grepping and using find or search tools, digging all around the code base, to find the stinking function definition. Once I find it, I forget where I was, and I have to repeat it all over again for every single function, every single time I edit a library module using this approach. It's just bad. The opaque pointer approach above works fantastic instead, and the public pointer approach would be easy too.
Now, to directly answer your questions:
To make common operations on these struct instances easier for library consumers, can I provide function pointers to such functions inside the struct itself?
Yes you can, but it only makes calling something easier. Don't do it. Finding the function to look at its implementation becomes really hard.
Is it a good practice?
No, use Option 1 or Option 2 above instead, where you now just have to call C "namespaced" "methods" on every C "object". You must simply pass the "members of the C class" into the function as the first argument for every call instead. This means instead of in C++ where you can do:
myclass.dosomething(int a, int b);
You'll just have to do in object-based C:
// Notice that you must pass the "guts", or member data
// (`mylibrarymodule` here), of each C "class" into the namespaced
// "methods" to operate on said C "class object"!
// - Essentially you're passing around the guts (member variables)
// of the C "class" (which guts are frequently referred to as
// "private data", or just `priv` in C lingo) to each function that
// needs to operate on a C object
mylibrarymodule_dosomething(mylibrarymodule_h mylibrarymodule, int a, int b);
Would there be issues with respect to multithreading where a utility function is called in parallel with different arguments and so on?
Yes, same as in any multithreaded situation where multiple threads are trying to access the same data. Just add a mutex to each C struct-based "object", and be sure each "method" acting on your C "objects" properly locks (takes) and unlocks (gives) the mutex as required before operating on any shared volatile members of the C "object".
Related:
Opaque C structs: how should they be declared? [use "Object-based" C architecture]
I would like to suggest you reading com specification, you will gain a lot. all these com, ole and dcom technology is based on a simple struct that incorporates its own data and methods.
https://www.scribd.com/document/45643943/Com-Spec
simplied more here
http://www.voidcn.com/article/p-fixbymia-beu.html

Why are functions not considered first class citizens in C

In C (and so many other "low-level" languages), functions have a type. You can declare a variable with a type that matches a function and can assign a function to such a variable, yet people insists that functions are not first class citizen in C.
Using pointers to functions and passing functions to other functions as arguments is key in several standard functions in C; qsort for example, require a comparison function to be passed or it can't do anything.
It is not uncommon to see "object-oriented" programming in C, by declaring a struct with several variables with function-types. Callbacks can be and often are (if not always -- I can't imagine any other way to do it) implemented using variables with function-types or structs with members with function types.
So, why aren't functions considered first class citizens in C?
(I'm sure this is duplicate, but I can't seem to find any similar questions here)
There's a really good answer by Andreas Rossberg on a Scala question (near-duplicate) that happens to explain why functions in C/C++ aren't first class functions. To quote:
Being "first-class" is not a formally defined notion, but it generally means that an entity has three properties:
It can be used, without restriction, wherever "ordinary" values can, i.e., passed and returned from functions, put in containers, etc.
It can be constructed, without restriction, wherever "ordinary" values can, i.e., locally, in an expression, etc.
It can be typed in a way similar to "ordinary" values, i.e., there is a type assigned to such an entity, and it can be freely composed with other types.
For functions, (2) particularly implies that a local function can use all names in scope, i.e. you have lexical closures. It also often comes with an anonymous form for construction (such as anonymous functions), but that is not strictly required (e.g. if the language has general enough let-expressions). Point (3) is trivially true in untyped languages.
...
Functions in C/C++ are not first-class. While (1) and (3) are arguably available through function pointers, (2) is not supported for functions proper. (A point that's often overlooked.)
Emphasis mine
Adding an example to the theory explanation by hnefatl. In C, int values are first class. We can add two int values, creating a new int value:
int add(int a, int b)
{
return a + b;
}
Similarly in Haskell, we can compose two functions (of appropriate type) to create a new function:
compose f g = f . g
h = compose f g is the function such that h(x) = f(g(x)).
Such an operation can't be done in C, to my knowledge. The same effect can be achieved through other means in C of course. But we cannot compute new functions as easily and naturally as we can numbers.
I think wikipedia has a better explanation of this concept. The key to first-class functions is whether a language supports closures, which raises the funarg problem if a returned function refers to variables defined in the outer environment.
Apparently, C doesn't support that.

Convert typedef struct from C to Pascal

I'm trying to convert a C-Header to pascal, but I'm struggling with the following line:
typedef struct GLFWwindow GLFWwindow;
Since I'm not very good at C I can't even figure out what this statement means. Therefor I'm also unable to translate it.
Is it some kind of anonymous structure or maybe a handle? In the subsequent code it's usually referred to as follows:
typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);
The thing which confuses me the most is, that the structure is not defined anywhere (it has no member?!). I assume the answer is incredibly simple but nevertheless I hope someone will help me :)
Afaik yes, it is a forward define, making the struct opague, but the final struct should be declared before use in the implementation.
This construct has no direct equivalent in Pascal, best replaced by a single "pointer" or a pointer to an empty record.
The second construct is a procedure type declaration
type
PGLFWWindow = ^GLFWWindow; // pointer types need explicit declaration
// in most modern pascals
TGLFWwindowposfun = Procedure (param1:PGLFFwindowposfun;
param2,param3:integer);cdecl;
Note
prefix "P", "T", delphi style, since all identifiers share one namespace base classes of identifiers are separate by hungarian prefix notation (P=pointer, T=type etc).
The GLFWindow type is better also prefix with T, for consistency.
The integer type is usually the same as C, but e.g. in the default mode FreePascal integer is 16-bit (for TP compatibility). If you use FPC, ctypes.cint is the best fit for C's integer.
Since the default Pascal calling convention is usually not the same as C's on x86, I applied a calling convention modifier cdecl which means "C calling convention".
addendum to be clear, GLFWINDOW would be an empty record (GLWINDOW= record end;), not a pointer to an empty record.

Private Keyword in a C Struct

Today, I have just noticed a statement in a C struct, and to be honest I was like WTF at first. It is like;
struct foo {
void *private;
//Some other members
};
Believe or not this struct is being compiled without any error. So what is the purpose of adding such a line (void *private)?
In pure C there's no private keyword, so the above is perfectly legal, albeit a very bad idea.
This would be invalid C++ though, and a C++ compiler would surely yield an error.
void* are in C often used to hide the actual data type used, effectively hiding some implementation details from the interface.
Actually you have stumbled upon an important difference between C and C++, the way structures are implemented.
In C, structures contains can contain only primitive and composite datatypes, whereas C++ structures gives more functionality, since the structures in C++ are similar to classes than structures in C, hence they provide additional functionality such as
Ability to classify members as private,public or protected.
Can contain member functions.
Structures in C++, can be used as a tool to enforce object oriented methods, since all OO functionality like inheritance, which is applicable to classes , holds good for structures as well.
So in short, the above code is valid C, but invalid C++.

c classes functions

Ok this may be a silly question for many of you.
Let me preface this with a list in order of the languages I've learned over the past 10 years.
[by the way, I understand that some of these are scripting languages]
vb 6.0
html
asp
php
css
javascript
managed c++
c#
c++
C
ASM
Yeah I know I started at the complete opposite end, but hopefully the list keeps me from getting criticized to much with this one heh.
QUESTION: Are there classes in plain old C...I know there are structures...
Also I would like to know if you can declare functions in C structures/classes(if they exist).
I think the answer to both is no, but It's hard to find information on plain C on the internet as most things are for C++. Also, I am interested in knowing any tips, tricks, or warning for working with C. Much thanks in advance.
BTW: I'm interested in C for the purpose of portability and speed.
Classes in C are most often simulated by structs combined with function pointers. Non-virtual functions can be passed alongside a pointer to the struct, like so:
int obj_compare_funct(Obj *a, Obj *b);
int result = compare_two_objects(obj1, obj2, obj_compare_func);
But the real fun starts when you embed the pointers in the struct; this means objects of the same overall "class" can have different "methods". The biggest syntactic downside is that the function pointed to does not automatically know for which object it is being called. So the object needs to be passed as well, which makes for a bit more typing than is normally desirable. For instance:
/***** In the animal.h header file. *****/
typedef struct Animal {
char *name;
void (* speak)(Animal *this); /* The speak "method" */
} Animal;
/* Constructors for various animal types. Implementation detail: set the animal's speak method to the appropriate one for that animal type. */
extern Animal *make_feline(char *name);
extern Animal *make_rodent(char *name);
/***** Somewhere in zoo.c, which #includes animal.h. *****/
Animal *cat = make_feline("Tom");
Animal *mouse = make_rodent("Jerry");
cat->speak(cat); /* Print "Tom says meow!" */
mouse->speak(mouse); /* Print "Jerry says squeak!" */
This example is a bit looser than the inheritance model provided by languages such as Java -- an Animal instance can have any behaviour at all, rather than one of a specific set of behaviours depending on its subclass. To make things a bit stricter, the methods are usually combined into a struct called a vtable (virtual function table). One vtable is pre-made for each subtype, and the appropriate one pointed to from the instance.
Note that none of this directly helps you have different fields for each subtype -- that's trickier (especially syntactically) and can be done either by the trick of casting an object to its first member, e.g.:
/* Can be treated as an Animal if you cast its pointer. */
typedef struct Cat { Animal super; int num_fleas; } Cat;
Or using opaque pointers, e.g.
typedef struct Animal { char *name; void *species_specific_data; } Animal;
Where the extra fields would be hidden away behind that void * pointer, and accessible through the methods particular to that species.
C doesn't have classes. That was one reason for the creation of C++, besides function overloading, operator overloading, and templates.
Of course, code acting class-like was sometimes written long before the existence of C++:
typedef struct class1 class1;
struct class1 {
int (*constructor) (class1 *this);
int (*destructor) (class1 *this);
...
};
C has no classes, and structs in C cannot have functions within them.
There are many differences between C and C++ structs, and yes C doesn't have classes.
For example consider the following code:
struct demo
{
int a;//public by default
void set()// valid in C++, invalid in C
{
//do something with a
}
};
Other differences between C and C++ structs are:
->Constructors and destructors for object initialization and destruction purpose.
->Support of operator overloading, templates,exception handling mechanism etc in C++ structs.
Properties shared between structs in C and POD-structs in C++:
1)Data members are allocated so that later members have higher addresses within an object, except where separated by an access-specifier.
2)Two POD-struct types are layout-compatible if they have the same number of nonstatic data members, and corresponding nonstatic data members (in order) have layout-compatible types.
A POD-struct may contain unnamed padding.
3)A pointer to a POD-struct object, suitably converted using a reinterpret cast, points to its initial member and vice versa, implying that there is no padding at the beginning of a POD-struct.
4)A POD-struct may be used with the offsetof macro.
Source -wiki
Remember that C was created in 1972, well before the ideas of object-oriented programming was common. At the time, object-oriented programming was limited to very few languages, like Simula 67.
So, no, C does not have classes.

Resources