c classes functions - c

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.

Related

When does it make sense to use a struct without a typedef?

Structs in C declare a data structure that associates different data types into a contiguous piece of memory.
Typedefs are a way to create user-defined data type names. This is useful for many applications including <stdint.h>
Structs seem to be exclusively used with typedefs. It seems like the default behaviour of defining a struct should also define a typedef.
Why would I ever want to define struct without also using a typedef?
It's a matter of personal preference, possibly imposed onto other people working on the same project as a convention. For instance, the Linux kernel coding style guide discourages the introduction of new typedefs in no uncertain terms.
Though I don't necessarily agree with everything in that guide, some of which seems silly (for instance vps_t a; example could be virtual_container_t a;: the issue hinges on the cryptic name that is chosen for typedef more than the existence of the typedef), in my TXR language project, here are some raw stats:
txr$ git grep '^typedef struct' '*/*.[ch]' '*.[ch]' | wc
25 91 839
txr$ git grep '^struct' '*/*.[ch]' '*.[ch]' | wc
135 528 4710
Lines of code beginning with struct outnumber typedef struct lines by a factor of 5.4!
The union/tag namespace feature of C means that you can have a variable called foo in the same scope as a struct foo without a clash, which is useful. This extra namespace gives us an opportunity not to pollute the regular identifier namespace with user-defined type names, which improves hygiene.
The cost is that we have to type struct foo instead of just foo in declarations.
It makes particular sense if you have experience with languages in which class/type names do not intrude into the lexical variable namespace, like Common Lisp.
The above code base, though, compiles as C++, so that throws a bit of a monkey wrench into it. In C++, struct foo defines foo as a type, which can be referenced in the ordinary namespace.
Another reason is that there is some clarity. When we see a declaration like:
struct foo x;
we know that x is a structure, whereas
foo x;
could be anything; it could be typedef double foo. Sometimes we go for that kind of abstraction. When you want to hide how something is implemented, reach for typedef. However, typedef doesn't provide perfect abstraction.
Also, if we see:
struct foo f;
struct bar b;
we know that these are necessarily different, incompatible types. We do not know that given:
foo f;
bar b;
They could both be typedefs for the same structure or for int for all we know.
If you typedef pointer types, but the code dereferences them, it looks pretty silly:
foo x = get_foo();
char *fname = x->name; /* what? */
That kernel coding style document has this to say about the above: In general, a pointer, or a struct that has elements that can reasonably be directly accessed should never be a typedef.
Not using typedef for structures has as much to do with some of the hygiene of using the tag namespace, as it has to do with avoiding typedef as such: keeping the code explicit, and reserving typedef for situations in which we actually need a proper abstraction.
Structs seem to be exclusively used with typedefs.
This is a mistaken impression. Structs are frequently used without typedefs, and I personally prefer that. There are numerous struct types declared and used, without built-in typedefs, by the C standard library and POSIX standard library extension functions, for example.
It seems like the
default behavior of defining a struct should also define a typedef.
In C++, it effectively does.
Why would I ever want to define struct without also using a typedef?
Why would you ever want to define a struct with a typedef? Using a (tagged) structure type via the struct keyword and its tag clarifies what kind of type it is, and enables you to determine quickly by eye whether two types are the same. On the other hand, a typedefed alias can represent any type at all, and there can be multiple such aliases for the same type.
There are some good and appropriate uses of typedef, but there are a lot of other uses whose propriety is a code style consideration. Myself, I strongly prefer styles that minimize use of typedef.
typedef is just a convenience to allow you to refer to your struct without explicitly stating struct MyStruct every time you refer to it.
Some actually prefer this explicitness, making it clear you're working with a user-defined type.
I never typedef my structs so that they can be "extern" declared in other headers easier.
You ask: Why would I ever want to define struct without also using a typedef?
It depends what you mean by 'define a struct'. Not all uses of struct are to define named types.
For example you could define a variable via
struct
{ double a, b;
} dbls = { -1.0, 1.0};
Then dbls.a etc makes sense, but there is no named type.
Similarly in an anonymous union you might have
struct ructT
{ union
{ struct { int a; int b; } ints;
struct { float a; float b; } floats;
};
};
Here one has defined a type struct ructT but the inner structs are unnamed.
In each of these cases if one was to insist on typedefs, there would be more names to dream up, and more code to type.
typedef isn't just about saving a few keystrokes - it's about abstracting away implementation details of the underlying type. IOW, if you provide a typedef name for a struct type, you should also provide a complete API for setting and accessing members, formatting for output, allocating, deallocating, etc. You're hiding the "struct"-ness of the type from whomever is using it. Think about the FILE type in the standard library - that's a typedef name, usually for some implementation-specific structure. However, you never access any element of a FILE type directly - you just pass FILE * objects to various functions (fprintf, fread, feof, ferror, etc.) that hide the implementation from you.
If you're expecting the user of the type to explicitly access members with the . or -> operators, then don't create a typedef name for it - just leave it as struct whatever. Otherwise you create a "leaky" abstraction, which creates heartburn down the line.
Similar rule for pointer types - don't hide the "pointer"-ness of a type behind a typedef unless you're willing to create a full API to abstract away pointer operations as well.

How create user-defined types in C?

For unknown reasons, I need to know how to replace the standard char a[10]; with string a; (Yes, I saw it in the CS50). So, how to create your own variable type named string?
Amplifying on what #Lundin said in his answer:
One of the things that makes C hard to learn -- especially for students coming from other languages -- is that C does not have a first-class "string" type. Important as they are, strings in C are cobbled together out of arrays of char, and often accessed via char * pointers. The cobbling together is performed by a loose collaboration between the compiler, the programmer, and library functions like strcpy and printf.
Although I said that "strings are cobbled together out of arrays of char, and often accessed via char * pointers", this does not mean that C's string type is char [], and it also does not mean that C's string type is char *.
If you imagine that C has a first-class string type, handled for you automatically by the language just like char, int, and double, you will be badly confused and frustrated. And if you try to give yourself a typedef called string, this will not insulate you from that confusion, will not ease your frustration, will not make your life easier in any way. It will only cloud the issue still further.
It is as simple as typedef char string[10];.
But please don't do this. Hiding arrays or pointers behind a typedef is very bad practice. The code gets much harder to read and you gain nothing from it. See Is it a good idea to typedef pointers? - the same arguments apply to arrays.
It is particularly bad to name the hidden array string since that is the exact spelling used by C++ std::string.
Please note that the CS50 is a bad course since it teaches you to do this. The SO community is sick and tired of "un-teaching" bad habits to the victims of this course. Stay away from questionable Internet tutorials in general.
If you want to create some manner of custom string type, the correct and proper way is to use a struct instead.
User defined types in C are structures, unions, enumerations and functions. And it seems you can also include arrays in the list.
For example
struct Point
{
int x;
int y;
};
or
enum Dimension { N = 100 };
Point a[N];
In this example the array type is Point[N].
In fact any derived type (including pointers) can be considered as a user-defined type. The C Standard does not define and use the tern user-defined type.
User defined types are one of the following: struct, union or enum. For example, struct:
struct worker {
int id;
char firstName[255];
char lastName[255];
};
To create an instance:
struct worker w1 = { 1234, "John", "Smith" };

Typedef struct declared as two types: "typedef struct x { .. } X, *XPointer"

Sorry if this has been asked before, I wasn't really even sure what to search for to come up with this.
When I create a typedef struct, I usually do something like this:
typedef struct myStruct {
int a;
int b;
struct myStruct *next;
} MyStruct;
So I declare it with MyStruct at the end. Then when I create functions that pass that in as a parameter, I write
int doSomething(MyStruct *ptr){
}
Yet I am collaborating with a friend on a project and I have come across his coding style, which is to also declare *MyStructP like this:
typedef struct myStruct {
int a;
int b;
struct myStruct *next;
} MyStructR, *MyStructP;
And then he uses MyStructP in his functions, so his parameters look like:
int doSomething(MyStructP)
So he doesn't have to use the * in the parameter list. This confused me because when I look at the parameter list, I always look for the * to determine if the arg is a pointer or not. On top of that, I am creating a function that takes in a struct I created and a struct he created, so my arg has the * and his does not. Ultra confusing!!
Can someone give insight/comparison/advice on the differences between the two? Pros? Cons? Which way is better or worse, or more widely used? Any information at all. Thanks!
It is generally considered poor style to hide pointers behind typedefs, unless they are meant to be opaque handles (for example SDL_GLContext is a void*).
This being not the case here, I agree with you that it's more confusing than helping.
The Linux kernel coding style says to avoid these kinds of typedefs:
Chapter 5: Typedefs
Please don't use things like "vps_t".
It's a mistake to use typedef for structures and pointers. When you see a
vps_t a;
in the source, what does it mean?
In contrast, if it says
struct virtual_container *a;
you can actually tell what "a" is.
Some people like to go with ideas from Hungarian Notation when they name variables. And some people take that concept further when they name types.
I think it's a matter of taste.
However, I think it obscures things (like in your example) because you'd have to dig up the declaration of the name in order to find its type. I prefer things to be obvious and explicit, and I would avoid such type names.
(And remember, typedef does not introduce a new type but merely a new name that aliases a new type.)
The main good reason why people occasionally typedef pointers is to represent the type as a "black box object" to the programmer and to allow its implementation to more easily be changed in the future.
For example, maybe today the type is a pointer to a struct but tomorrow the type becomes an index into some table, a handle/key of some sort, or a file descriptor. Typedef'ing this way tells the programmer that they shouldn't try things they might normally do to a pointer such as comparing it against 0 / NULL, dereferencing it (e.g. - directly accessing members), incrementing it, etc., as their code may become broken in the future. Of course, using a naming convention, such as your friend did, that reveals and encodes that the underlying implementation actually is a pointer conflicts with that purpose.
The other reason to do this is to make this kind of error less likely:
myStructR *ptr1, ptr2;
myStructP ptr3, ptr4;
That's pretty weak sauce as the compiler will typically catch you misusing ptr2 later, but that is a reason given for doing this.

multilevel inheritance in c

when doing inheritance in pure C like this
typedef struct {
char name[NAMESIZE];
char sex;
} Person;
typedef struct {
Person person;
char job[JOBSIZE];
} Employee;
typedef struct {
Person person;
char booktitle[TITLESIZE];
} LiteraryCharacter;
I know it is okay to cast a instance of type "LiteraryCharacter" to type "Person", and use it as such. But is it also ok/safe to cast a instance of type "LiteraryCharacter" to type "Employee" and use it as such?
Such a cast is undefined behavior in standard C, although it will work with many compilers.
Even if it works on a compiler you are currently using, be aware that it might break in a future version of the compiler, or with a different compiler. The C standard allows the compiler to assume that pointers to different types don't point to the same memory - except for some well-documented exceptions, which include cast of LiteraryCharacter * to Person *. The code that casts LiteraryCharacter * to Employee * can and will break under a compiler that makes use of this assumption to generate efficient code.
It might be a good idea to explain why you think you need this cast in the first place. Its equivalent would be quite incorrect in C++, and generate a ClassCastException in Java. After all, LiteraryCharacter doesn't have the fields of Person, such as job.
That would be undefined behaviour. There is no such thing as inheritance in C.
You might get away with it if the structures had exactly the same layout but that would be very brittle code indeed.
Undefined behavior:
In your example you are casting to-from incompatible types which doesn't even compile because of the differences in the sizes of those two types. You can however cast to-from compatible (or even incompatible) pointer types and it will compile.
Casting to-from incompatible (or rather pseudo-compatible) types is undefined behavior, on some structures and compiler implementations it will work on others it won't.
Casting to compatible -- pointer types is safe as long as the compiler is taking care of the object structure / internal alignments / memory layout, etc. (there's an example below).
The "OK" part is debatable. Will it work? Yes because they have the same "in memory" layout and you are aware of that particular fact. But what happens when another programmer created that structure? You have to read its source to assess if it can be safely cast to another type.
Encapsulation and future proofing:
Also most encapsulation techniques will only expose an "opaque type" which you can use via pointers -- pass it along to functions implemented within the same library/package and they do all of the structure specific work. In the case of "opaque types" you only know that that structure exists, you don't know it's internal structure so you can't just change the pointer type you're using to access it because you can't be sure of the structure compatibility behind it.
The point of encapsulation is to allow modules to be developed individually. So when the original developer of this external module changes the structure in a future version it breaks compatibility with your code (which shouldn't be using it that way anyway).
Safer way to do this:
This is a non standard (yet pretty much ubiquitous) compiler feature of GCC.
typedef struct {
char name[NAMESIZE];
char sex;
} Person;
typedef struct {
Person;
char job[JOBSIZE];
} Employee;
typedef struct {
Employee;
char booktitle[TITLESIZE];
} LiteraryEmployeeCharacter;
LiteraryEmployeeCharacter* lec = malloc(sizeof(LiteraryEmployeeCharacter));
lec->name = "My character";
lec->sex = 'F';
lec->job = "Steward";
lec->booktitle = "A book";
By using unnamed fields you get access to name, sex and job as if they were defined in the LiteraryEmployeeCharacter structure.
By casting to a compatible pointer type the compiler knows the exact structure and position of every field and ca easily handle the structure correctly.

why can't we declare functions inside a structure?

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.

Resources