I have got a question i am working on and this is as follows (with a bunch of constants that aren't relevant)
Use a struct to represent an (x, y) coordinate. A second struct must then be used to represent the sound source — its (x, y) coordinate and the W value. You will also need to declare an appropriate array of struct variables. You may assume that not more the 100 sound sources will be involved in the plant/site being analysed.
This is what i got so far;
struct point
{
double x, y;
};
/* for sound sources */
struct source
{
struct point location;
float power;
};
Is there anyway to rewrite this in a different way? or a 'more correct' way?
There is nothing wrong with what you have written, although it doesn't include the last part of your spec (the array).
There are many other ways to do this; how relatively "correct " they are to this one depends on what criteria you have for comparing them, none of which you have provided. Besides, that kind of discussion is better suited for a code review, and hence a question for a different site.
That looks fine, but there is another way to write this that I tend to prefer:
typedef struct tagPoint
{
double x, y;
} point, *pPoint;
typedef struct tagSource
{
point location;
float power;
} source, *pSource;
I find this method a bit cleaner, as you do not need to write out the struct each time you use the structure.
Related
For example, I have a given struct X. And now, I am defining additionally A, B and C. All of them contain the exact same attributes like X but contain also additional ones.
I've seen the following question: Extending a struct in C
I don't want to make use of this nested thing, also, I never use X itself. It is only a collection of attributes which appear in all other structures.
I was pondering about just defining the content of X as macro and use it in the definitions of the other structs. For example:
#ifndef
#define X \
char *some_char_arr; \
int *some_int_arr;
#endif
struct A {
X
int specific_to_a[10];
}
struct B {
X
int specific_to_b[20];
}
struct C {
X
int specific_to_c[30];
}
Would that be an adequate solution or is there something better? Or is there any problem with this approach?
While a macro like that would compile and work, it is generally considered bad practice due to readability and maintainability concerns.
The way inheritance is typically done in C is with nested structs, like in the linked answer. So you would have:
struct Base {
char *some_char_arr;
int *some_int_arr;
};
struct A {
struct Base base;
int specific_to_a[10];
};
If you don't like typing a.base.some_char_arr and would rather just type a.some_char_arr you can use anonymous structs as explained here (and which is supported by C11).
When I decided to teach myself to program, I started with Java. And although I'm familiar with writing simple procedural software (mostly in PHP), I've recently come to realize that for more complex operations I rely on objects.
My first Java game spawned opponents at random locations and with random speeds by instantiating objects. I am puzzled by the concept of implementing this procedurally in C (which I have very little working knowledge of), but I could only think of creating different arrays for the variables in each opponent and using the array indices as pseudo-object reference 'variables'.
int size[50]; // opponent size
for (i = 0; i < 100; i++) {
size[i] = random_number();
}
Is there a simple solution that my object-oriented mind has overlooked? Or do certain problems really lend themselves to object-oriented concepts to the extent that you have to make up fake objects (or at least use similar models)? I see structs in C code all the time, and I know they're similar to classes in concept, but that's all I know. So I'm wondering if stuff like this is possible with a totally non object-oriented mindset. There's no real substitute for instantiation, is there? It's all just allocation of memory, so the way I see it, certain C programs have no choice but to be written using some form of what I consider objects.
Please tell me I'm overlooking something, because otherwise I can't respect C purists who berate the object-oriented paradigm. (I'm by no means an OO nut; my mind has become very accustomed to the idea, though, and it's hard to see things through a different lens that doesn't offer what you're used to.)
Thanks!
As someone who also started out as an OO programmer, it's also taken me a bit to get used to procedural programming. The biggest thing for me is getting used to working with pointers, and remembering that functions are not managed by an object, and instead act on an "object" which you give them. Anyway, I think something like this might be what you're looking for to help you get a procedural image of what you're trying to do.
struct creature {
int speed;
int size;
};
void init_creature(struct creature *c) {
c->speed = random_number();
c->size = random_number();
}
int main() {
struct creature creatures[10];
for (int i = 0; i < (sizeof(creatures)/sizeof(struct creature)); i++) {
struct creature c = creatures[i];
init_creature(&c);
}
}
If we neglect all advanced object oriented programming concepts, as inheritance or polymorphism by type parameters everything boils down to the same thing.
In C++ you have objects and you call methods that are attached to them, in C you have structs and you call global functions by passing these functions by argument.
What I mean is that the essential oop paradigm is conceptually to have objects which are able to perform things through their methods. Now in C you can obtain the same behavior but you have functions which are not attached to any object.
So basically in C++ or Java you would have:
class Point {
private:
int x, y;
public:
Point(int x, int y) : x(x), y(y) { }
void draw() { ... }
};
In pure C you would have:
struct Point {
int x, y;
}
struct Point makePoint(int x int y) {
struct Point p = {.x = x, .y = y};
return p;
}
void drawPoint(struct Point p) {
..
}
But the semantic power of both representation is essentially the same, the syntax is different though (and even the concept behind it). Of course everything changes if we start considering more powerful oop features.
In many circumstances you don't need all this power to represent objects, not everything is meant to be oop neither all problems are best solved with an oop approach. If writing a complex engine for a game in C would be overkill at the same time writing low level functions in Java which operates with the system would be overkill at the same time.
A struct is probably what you are looking for here.
A struct can contain any number of named variables (like properties on a class) but can't contain methods (theoretically you could put methods in it via function pointers, but that won't really work the way you want it to).
So representing your creatures in C, you might have a struct like this:
struct creature {
int x_pos;
int y_pos;
int speed;
};
To declare a creature "object" and set some properties, you would do so like this:
void main() {
struct creature mycreature;
mycreature.x_pos = 1;
mycreature.y_pos = 2;
}
The struct creature mycreature syntax is a bit unwieldy, so people often typedef structs so they don't have to say struct creature mycreature and can instead just say creature mycreature:
typedef struct _creature {
int x_pos;
int y_pos;
int speed;
} creature;
A struct can contain other structs, so you might also create a point struct and use that for the location variables instead:
typedef struct _point {
int x;
int y;
} point;
typedef struct _creature {
point location;
int speed;
} creature;
void main() {
creature mycreature;
mycreature.location.x = 1;
mycreature.location.y = 2;
}
And now things hopefully start to look a bit more familiar...
In the question Why should we typedef a struct so often in C?, unwind answered that:
In this latter case, you cannot return
the Point by value, since its
declaration is hidden from users of
the header file. This is a technique
used widely in GTK+, for instance.
How is declaration hiding accomplished? Why can't I return the Point by value?
ADD:
I understood why I can't return the struct by value, but, is still hard to see why i can't deference this point in my function. i.e. If my struct have member named y, why i can't do it?
pointer_to_struct->y = some_value;
Why should I use methods to do it? (Like Gtk+)
Thanks guys, and sorry for my bad english again.
Have a look at this example of a library, using a public header file, a private header file and an implementation file.
In file public.h:
struct Point;
struct Point* getSomePoint();
In file private.h:
struct Point
{
int x;
int y;
}
In file private.c:
struct Point* getSomePoint()
{
/* ... */
}
If you compile these three files into a library, you only give public.h and the library object file to the consumer of the library.
getSomePoint has to return a pointer to Point, because public.h does not define the size of Point, only that is a struct and that it exists. Consumers of the library can use pointers to Point, but can not access the members or copy it around, because they do not know the size of the structure.
Regarding your further question:
You can not dereference because the program using the library does only have the information from private.h, that does not contain the member declarations. It therefore can not access the members of the point structure.
You can see this as the encapsulation feature of C, just like you would declare the data members of a C++ class as private.
What he means is that you cannot return the struct by-value in the header, because for that, the struct must be completely declared. But that happens in the C file (the declaration that makes X a complete type is "hidden" in the C file, and not exposed into the header), in his example. The following declares only an incomplete type, if that's the first declaration of the struct
struct X;
Then, you can declare the function
struct X f(void);
But you cannot define the function, because you cannot create a variable of that type, and much less so return it (its size is not known).
struct X f(void) { // <- error here
// ...
}
The error happens because "x" is still incomplete. Now, if you only include the header with the incomplete declaration in it, then you cannot call that function, because the expression of the function call would yield an incomplete type, which is forbidden to happen.
If you were to provide a declaration of the complete type struct X in between, it would be valid
struct X;
struct X f(void);
// ...
struct X { int data; };
struct X f(void) { // valid now: struct X is a complete type
// ...
}
This would apply to the way using typedef too: They both name the same, (possibly incomplete) type. One time using an ordinary identifier X, and another time using a tag struct X.
In the header file:
typedef struct _point * Point;
After the compiler sees this it knows:
There is a struct called _point.
There is a pointer type Point that can refer to a struct _point.
The compiler does not know:
What the struct _point looks like.
What members struct _point contains.
How big struct _point is.
Not only does the compiler not know it - we as programmers don't know it either. This means we can't write code that depends on those properties of struct _point, which means that our code may be more portable.
Given the above code, you can write functions like:
Point f() {
....
}
because Point is a pointer and struct pointers are all the same size and the compiler doesn't need to know anything else about them. But you can't write a function that returns by value:
struct _point f() {
....
}
because the compiler does not know anything about struct _point, specifically its size, which it needs in order to construct the return value.
Thus, we can only refer to struct _point via the Point type, which is really a pointer. This is why Standard C has types like FILE, which can only be accessed via a pointer - you can't create a FILE structure instance in your code.
Old question, better answer:
In Header File:
typedef struct _Point Point;
In C File:
struct _Point
{
int X;
int Y;
};
What that post means is: If you see the header
typedef struct _Point Point;
Point * point_new(int x, int y);
then you don't know the implementation details of Point.
As an alternative to using opaque pointers (as others have mentioned), you can instead return an opaque bag of bytes if you want to avoid using heap memory:
// In public.h:
struct Point
{
uint8_t data[SIZEOF_POINT]; // make sure this size is correct!
};
void MakePoint(struct Point *p);
// In private.h:
struct Point
{
int x, y, z;
};
void MakePoint(struct Point *p);
// In private.c:
void MakePoint(struct Point *p)
{
p->x = 1;
p->y = 2;
p->z = 3;
}
Then, you can create instances of the struct on the stack in client code, but the client doesn't know what's in it -- all it knows is that it's a blob of bytes with a given size. Of course, it can still access the data if it can guess the offsets and data types of the members, but then again you have the same problem with opaque pointers (though clients don't know the object size in that case).
For example, the various structs used in the pthreads library use structs of opaque bytes for types like pthread_t, pthread_cond_t, etc. -- you can still create instances of those on the stack (and you usually do), but you have no idea what's in them. Just take a peek into your /usr/include/pthreads.h and the various files it includes.
I'm having a very big struct in an existing program. This struct includes a great number of bitfields.
I wish to save a part of it (say, 10 fields out of 150).
An example code I would use to save the subclass is:
typedef struct {int a;int b;char c} bigstruct;
typedef struct {int a;char c;} smallstruct;
void substruct(smallstruct *s,bigstruct *b) {
s->a = b->a;
s->c = b->c;
}
int save_struct(bigstruct *bs) {
smallstruct s;
substruct(&s,bs);
save_struct(s);
}
I also wish that selecting which part of it wouldn't be too much hassle, since I wish to change it every now and then. The naive approach I presented before is very fragile and unmaintainable. When scaling up to 20 different fields, you have to change fields both in the smallstruct, and in the substruct function.
I thought of two better approaches. Unfortunately both requires me to use some external CIL like tool to parse my structs.
The first approach is automatically generating the substruct function. I'll just set the struct of smallstruct, and have a program that would parse it and generate the substruct function according to the fields in smallstruct.
The second approach is building (with C parser) a meta-information about bigstruct, and then write a library that would allow me to access a specific field in the struct. It would be like ad-hoc implementation of Java's class reflection.
For example, assuming no struct-alignment, for struct
struct st {
int a;
char c1:5;
char c2:3;
long d;
}
I'll generate the following meta information:
int field2distance[] = {0,sizeof(int),sizeof(int),sizeof(int)+sizeof(char)}
int field2size[] = {sizeof(int),1,1,sizeof(long)}
int field2bitmask[] = {0,0x1F,0xE0,0};
char *fieldNames[] = {"a","c1","c2","d"};
I'll get the ith field with this function:
long getFieldData(void *strct,int i) {
int distance = field2distance[i];
int size = field2size[i];
int bitmask = field2bitmask[i];
void *ptr = ((char *)strct + distance);
long result;
switch (size) {
case 1: //char
result = *(char*)ptr;
break;
case 2: //short
result = *(short*)ptr;
...
}
if (bitmask == 0) return result;
return (result & bitmask) >> num_of_trailing_zeros(bitmask);
}
Both methods requires extra work, but once the parser is in your makefile - changing the substruct is a breeze.
However I'd rather do that without any external dependencies.
Does anyone have any better idea? Where my ideas any good, is there some availible implementation of my ideas on the internet?
From your description, it looks like you have access to and can modify your original structure. I suggest you refactor your substructure into a complete type (as you did in your example), and then make that structure a field on your big structure, encapsulating all of those fields in the original structure into the smaller structure.
Expanding on your small example:
typedef struct
{
int a;
char c;
} smallstruct;
typedef struct
{
int b;
smallstruct mysub;
} bigstruct;
Accessing the smallstruct info would be done like so:
/* stack-based allocation */
bigstruct mybig;
mybig.mysub.a = 1;
mybig.mysub.c = '1';
mybig.b = 2;
/* heap-based allocation */
bigstruct * mybig = (bigstruct *)malloc(sizeof(bigstruct));
mybig->mysub.a = 1;
mybig->mysub.c = '1';
mybig->b = 2;
But you could also pass around pointers to the small struct:
void dosomething(smallstruct * small)
{
small->a = 3;
small->c = '3';
}
/* stack based */
dosomething(&(mybig.mysub));
/* heap based */
dosomething(&((*mybig).mysub));
Benefits:
No Macros
No external dependencies
No memory-order casting hacks
Cleaner, easier-to-read and use code.
If changing the order of the fields isn't out of the question, you can rearrange the bigstruct fields in such a way that the smallstruct fields are together, and then its simply a matter of casting from one to another (possibly adding an offset).
Something like:
typedef struct {int a;char c;int b;} bigstruct;
typedef struct {int a;char c;} smallstruct;
int save_struct(bigstruct *bs) {
save_struct((smallstruct *)bs);
}
Macros are your friend.
One solution would be to move the big struct out into its own include file and then have a macro party.
Instead of defining the structure normally, come up with a selection of macros, such as BEGIN_STRUCTURE, END_STRUCTURE, NORMAL_FIELD, SUBSET_FIELD
You can then include the file a few times, redefining those structures for each pass. The first one will turn the defines into a normal structure, with both types of field being output as normal. The second would define NORMAL_FIELD has nothing and would create your subset. The third would create the appropriate code to copy the subset fields over.
You'll end up with a single definition of the structure, that lets you control which fields are in the subset and automatically creates suitable code for you.
Just to help you in getting your metadata, you can refer to the offsetof() macro, which also has the benefit of taking care of any padding you may have
I suggest to take this approach:
Curse the guy who wrote the big structure. Get a voodoo doll and have some fun.
Mark each field of the big structure that you need somehow (macro or comment or whatever)
Write a small tool which reads the header file and extracts the marked fields. If you use comments, you can give each field a priority or something to sort them.
Write a new header file for the substructure (using a fixed header and footer).
Write a new C file which contains a function createSubStruct which takes a pointer to the big struct and returns a pointer to the substruct
In the function, loop over the fields collected and emit ss.field = bs.field (i.e. copy the fields one by one).
Add the small tool to your makefile and add the new header and C source file to your build
I suggest to use gawk, or any scripting language you're comfortable with, as the tool; that should take half an hour to build.
[EDIT] If you really want to try reflection (which I suggest against; it'll be a whole lot of work do get that working in C), then the offsetof() macro is your friend. This macro returns the offset of a field in a structure (which is most often not the sum of the sizes of the fields before it). See this article.
[EDIT2] Don't write your own parser. To get your own parser right will take months; I know since I've written lots of parsers in my life. Instead mark the parts of the original header file which need to be copied and then rely on the one parser which you know works: The one of your C compiler. Here are a couple of ideas how to make this work:
struct big_struct {
/**BEGIN_COPY*/
int i;
int j : 3;
int k : 2;
char * str;
/**END_COPY*/
...
struct x y; /**COPY_STRUCT*/
}
Just have your tool copy anything between /**BEGIN_COPY*/ and /**END_COPY*/.
Use special comments like /**COPY_STRUCT*/ to instruct your tool to generate a memcpy() instead of an assignment, etc.
This can be written and debugged in a few hours. It would take as long to set up a parser for C without any functionality; that is you'd just have something which can read valid C but you'd still have to write the part of the parser which understands C, and the part which does something useful with the data.
I'm trying to learn C and I've come across something weird:
struct
{
int i;
double j;
} x, y;
struct
{
int i;
double j;
} z;
Here, you can see I created two structs that are identical in their elements.
Why is it that when I try to assign x = z it will generate a compile error but x = y does not? They have the same contents, so why can't I assign them back and forth with each other, regardless?
Is there any way I can make this so I can assign x = z? Or do they simply have to be the same struct.
Can any C gurus point me in the right direction?
They have the same content, but not the same type. If they are intended to be of the same type, simply typedef x z;. If they aren't the same thing, but just happen to contain the same fields, it's better to create a separate function that will assign the fields properly.
My usual style for declaring structs in C includes the typedef, so I forgot to mention it (sorry!). Here's the syntax:
typedef struct
{
int foo;
double bar;
} x;
/* Further down, if needed */
typedef x z;
Making identically structured types the same is called "duck typing". This is done in some languages, but not in C.
The compiler does not calculate "type equivalence" between structs that may have the same structure, so as far as it is concerned, the second struct has nothing to do with the first one.
It can do x and y because they are declared at the same time.
Why are you redeclaring the struct ? You should probably typedef the struct once (e.g., in an H file) to make it an actual type, and then declare instances.
Here's a good tutorial on typedefs for structs.
struct mystruct
{
int i;
double j;
};
struct mystruct x, y;
struct mystruct z;
If you intend to copy data between them, you must declare them with the same identity. You have two declarations, it doesn't matter they are equal for the compiler, they are two different structures, and the compiler is not supposed to detect their similarity.
C differentiates structs based on name, and if they're anonymous, then different structure definitions are different.
Anyhow, classic C doesn't allow x = z when x and z are structs -- is that an ANSI or a C99 addition? Anyhow, you should instead use
#include <string.h>
memcpy(&x, &z, sizeof(x));