View Full Version : [SOLVED] Newbie C programming
AlexanderPike
February 19th, 2011, 01:53 AM
Hi I wanted to see, for no real reason other than to do it, if I could emulate object orientated methods with a C struct that has a function. Maybe my non-working code can work to explain what I mean :)
#include <stdio.h>
struct person{
char name[10];
void (*setname)();
}
int main(){
struct person test;
test.setname=&setname;
*(test.setname)(&test,"John");
printf("name: %s",test.name);
return 0;
}
void setname(struct person *self, char name[]){
self->name=name;
}
http://pastebin.com/0v1ziYnc
This yields:
gcc -o struc oo.c
oo.c:8: error: two or more data types in declaration specifiers
oo.c: In function âmainâ:
oo.c:10: error: âsetnameâ undeclared (first use in this function)
oo.c:10: error: (Each undeclared identifier is reported only once
oo.c:10: error: for each function it appears in.)
oo.c:11: error: void value not ignored as it ought to be
oo.c:13: error: incompatible types in return
oo.c:8: warning: return type of âmainâ is not âintâ
oo.c: In function âsetnameâ:
oo.c:16: error: incompatible types in assignment
I don't know what the funny characters are about maybe it's a putty thing?
MadCow108
February 19th, 2011, 02:19 AM
there are a few issues:
- a semicolon is missing after the closing bracket of the struct
- a forward declaration for setname is missing as it is defined below main
place this or the whole function before main:
void setname(struct person *self, char *name);
note I changed char name[]. I find this makes it clearer, see next point
- character arrays decay into pointers on stack changes, this includes function pointers. So char name[] is exactly same as char * name in a function declaration.
This makes clear that setname does not work. you have to do this:
#include <string.h>
void setname(struct person *self, char * name){
strncpy(self->name,name,sizeof(self->name));
// or safer version
strncpy(self->name,name,sizeof(self->name) - 1);
self->name[sizeof(self->name) - 1] = 0;
}
- the function pointer calling syntax is wrong. You are calling the function and dereferencing the result (which is void).
either this:
(*test.setname)(&test,"John")
//or
(test.setname)(&test,"John")
or a bit clearer:
(*(test.setname))(&test,"John")
cgroza
February 19th, 2011, 02:22 AM
In this line(9), you do not need to specify struct again:
struct person test;
Should be:
person test;
AlexanderPike
February 19th, 2011, 02:25 AM
Thanks MadCow108! It works perfectly now. Here's the completed code if anyone is interested.
#include <stdio.h>
#include <string.h>
struct person{
char name[10];
void (*setname)();
};
void setname(struct person *self, char *name);
int main(){
struct person test;
test.setname = &setname;
(*test.setname)(&test,"John");
printf("name: %s",test.name);
return 0;
}
void setname(struct person *self, char * name){
strncpy(self->name,name,sizeof(self->name));
}
MadCow108
February 19th, 2011, 02:25 AM
In this line(9), you do not need to specify struct again:
struct person test;
Should be:
person test;
in C you do need the struct. This is different in C++
you can only skip it if you do a typedef:
typedef struct mystruct {
...
} mystruct;
// or
struct mystruct_s {
...
};
typedef mystruct_s mystruct_t;
cgroza
February 19th, 2011, 02:27 AM
in C you do need the struct. This is different in C++
you can only skip it if you do a typedef:
typedef struct mystruct {
...
} mystruct;
// or
struct mystruct_s {
...
};
typedef mystruct_s mystruct_t;
I know that in C++ that is not necessary, and people say that they try to maintain compatibility.
Anyway, sorry for misleading information.
worksofcraft
February 19th, 2011, 02:57 AM
Thanks MadCow108! It works perfectly now. Here's the completed code if anyone is interested.
...
Yes that is an excellent bit of research into how Object orientedness might be done :)
Just incase you want to know more accurately what a C++ compiler would be generating... well it would be closer to this:
// gcc Cvtable.c ... this is straight C code for an OOP paradigm
#include <stdio.h>
#include <string.h>
// these just to make it more intelligible
typedef void (*fptr)();
typedef char * (*cptr)();
// all instances of person class must have a vtable pointer
struct person{
fptr *vtable;
char name[10];
};
// the methods of person class are setname and getname
void setname(struct person *self, char * name){
strncpy(self->name,name,sizeof(self->name));
}
char * getname(struct person *self){
return self->name;
}
// this is person class vtable
fptr person_vtable[] = {
(fptr) &setname,
(fptr) &getname
};
int main(){
// construct a person class instance
struct person test;
// which implies setting it's vtable pointer
test.vtable = person_vtable;
// call the setname method on this instance "test" of class person
(*test.vtable[0])(&test,"John");
// call the getname method on that instance
return !printf("name: %s\n", ((cptr) *test.vtable[1])(&test));
}
so now you also know what a vtable does cuz it means just setting ONE pointer in the object for ALL the virtual methods of said class :)
AlexanderPike
February 19th, 2011, 01:09 PM
That is pretty interesting. Would you say that was idomatic? I can imagine with alot of methods that works much better.
I just found this PDF which looks pretty interesting http://www.planetpdf.com/codecuts/pdfs/ooc.pdf discussing oo using ansi c, but it looks to be a pretty hefty read.
trent.josephsen
February 19th, 2011, 08:38 PM
Idiomatic C doesn't try to emulate C++.
worksofcraft
February 19th, 2011, 10:36 PM
That is pretty interesting. Would you say that was idomatic? I can imagine with alot of methods that works much better.
I just found this PDF which looks pretty interesting http://www.planetpdf.com/codecuts/pdfs/ooc.pdf discussing oo using ansi c, but it looks to be a pretty hefty read.
Soz IDK what idomatic means, but I do know that originally C++ was just done as preprocessor for standard C and then you could see it was producing that kind of thing for the compiler to compile.
Powered by vBulletin® Version 4.2.2 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.