I am currently writing a C program with a struct called Rectangle. The code below shows how I set it up.
typedef struct {
int width;
int height;
int x;
int y;
} Rectangle;
After that, I made another struct called Ellipse which contained exactly the same values as the Rectangle struct, as well as some more.
I wanted to keep my code neat so I decided to make a base struct called Shape.
I used this Shape struct in the header of my other structs.
typedef struct {
int width;
int height;
int x;
int y;
} Shape;
typedef struct {
Shape shape;
} Rectangle;
typedef struct {
Shape shape;
int angle;
int anchor_x;
int anchor_y;
} Ellipse;
Now whenever I make an instance of one of these structs, VSCode thinks there's an error.
Rectangle *rect;
rect -> width = 100;
VSCode puts an error squiggle under width that says struct "<unnamed>" has no field "width", but when I compile the code, it works perfectly.
Why does VSCode raise this error? Should I be doing things differently? How can I stop it from making unnecessary squiggles?
Please be patient, I am new to C programming.
You don't have a field width inside Rectangle - you have a field shape. Presumably what you wanted to do is rect->shape.width = 100.
Notice that your code won't work as-is because you never allocate memory for rect.
Related
I was trying to make a camera struct to handle a camera for an openGL tutorial in C.
// camera.h
#ifndef CAMERA_H
#define CAMERA_H
#include <stdbool.h>
#include <cglm/cglm.h>
struct camera
{
bool ortho;
float ratio;
vec3 pos, x, y, z;
float fov, yaw, pitch, roll;
mat4 view, projection, model;
};
int updateCamera(struct camera *c);
#endif
but when I compile (with clang) i get these two errors:
./src/visual/camera.h:7:1: warning: declaration does not declare anything [-Wmissing-declarations]
struct camera
^
./src/visual/camera.h:16:5: error: field 'updateCamera' declared as a function
int updateCamera(struct camera *c);
^
I do not understand what is wrong with the declared struct (the same errors appear for any other struct in the same file)
my guess would be that something is wrong in another file, but I do not know what to search, plus there aren't any included files
If somebody could give me any hint about what could be wrong, it would be greatly appreciated!
sry for my english & still beginner understanding of C🙃
After trying out everything that came to my mind, I finally found the answer:
I had another file (global.h) in which I included the camera.hfile. I have the habit to put #include just before the part of the code that requires tha specific file, to help me track my dependecies. Here it seemed to generate that problem because once I moved the #include "visual/camera.h" to the top of the file, the errors magically went away.
global.h before
struct game_state
{
float delta_time;
float speed;
#include "window/glfw.h"
struct window window;
#include "visual/camera.h"
struct camera camera;
};
struct game_state state;
global.h after the change, resolving the problem
#include "window/glfw.h"
#include "visual/camera.h"
struct game_state
{
float delta_time;
float speed;
struct window window;
struct camera camera;
};
struct game_state state;
I still do not understand what was wrong but hey, it works.
Thanks to everybody's answer, u made me learn new things !
Maybe the problem is that you are using C++ syntax in a C file.
Try this:
............
typedef struct
{
bool ortho;
float ratio;
vec3 pos, x, y, z;
float fov, yaw, pitch, roll;
mat4 view, projection, model;
} tCamera;
int updateCamera(tCamera *c);
............
I'm working on a function that works as part of a larger program. My C pointer skills are a bit rusty and so I need some help here.
Notice: I've omitted a lot of the program because it is irrelevant and works correctly, all you need to know is that I import a header file that declares the struct ImportedStruct, also, I cannot change the function header, so I need to pass the ImportedStruct as a pointer and the function as a pointer.
I get the following error message in VS code: pointer to incomplete class type is not allowed.
Any ideas?
#include "name.h"
long int *functionName(struct ImportedStruct *structName, int *irrelevant){
int width = structName->width;
int height = structName->height;
// Remaining function ...
}
Header file:
struct ImportedStruct
{
int width, height;
};
I just compiled the code you provide
struct ImportedStruct
{
int width, height;
};
long int *functionName(struct ImportedStruct *structName, int *irrelevant){
int width = structName->width;
int height = structName->height;
// Remaining function ...
return (long int *)(width + height);
}
and it compiled successfully.
Make sure struct definition is included.
Also, you can put
struct ImportedStruct
{
int width, height;
};
right before your function definition. If compiler does not give you multiple definition error, then struct definition is not included by headers.
I currently try to write some lil literal console game for fun in C.
For that, i need to be able to print window-like structures in ... well ... C.
I want to use a generic rendering method (lets call it frame_render(...)) to render all different "ui elements"
The problem now is: how to solve this?
given the scenario:
// Theoretical base
struct frame { int x; int y; int width; int height; }
struct button { int x; int y; int width; int height; ... }
struct whatever { int x; int y; int width; int height; ... }
how could i ensure that my x, y, width and height are always in the correct spot memory wise?
is it enough to "just" put them in the same order at the very begining?
also, how to design the method header to accept it?
If all of the structures start with members of the same types, in the same order, corresponding members will have the same offsets. Most compilers can be configured to allow a pointer of any structure type to be used to inspect members of the Common Initial Sequence of any other, but there are a few issues:
On some unusual platforms, if an object is followed by padding bytes, an instruction that writes the object and padding bytes together (likely storing meaningless values in the latter) may be faster than instructions that write only the object. If a member is followed by a padding byte in some structures, but by meaningful data in another, a write to that member using the type where it's followed by padding bytes may write overwrite the "padding bytes" with meaningless values, thus corrupting the values of the following members in the other structure types. I am unaware of any architectures in current use where this would be an issue for any struct members other than bitfields, and I am unaware of any current implementations where this would be an issue even for those, but such possibilities could arise on some platforms, especially with bitfields.
Given something like:
int readField1OfS1(struct s1 *p) { return p->field1; }
struct s2 *myStruct2Ptr;
if (readField1ofS1((struct s1*)myStruct2Ptr)
...
some compilers like gcc and clang won't reliably allow for the possibility that the value returned from the function might depend upon a value held by part of the Common Initial Sequence of an object of type struct s2 at the time of the call unless optimizations are disabled (e.g. using the -fno-strict-aliasing option). I would think that presence of a cast from struct s2* to struct s1* within the function call expression should allow a quality compiler to recognize that anything function might do something with an object of type struct s1 might be done on a struct s2, but since the Standard doesn't explicitly require that, the authors of gcc and clang refuse to make any effort to reliably recognize such constructs even in straightforward cases like the above.
Code which makes use of the Common Initial Sequence rule will work reliably on nearly any suitably-configured compiler, but some like gcc and clang must be specially configured using -fno-strict-aliasing option. The ability to exploit Common Initial Sequence guarantees has been a well-established part of the language since 1974, and when the Standard was written, anyone familiar with the language would have understood that it was designed to allow for constructs like those above, which compilers should have no difficulty recognizing. Since the authors of the Standard failed to explicitly require that the CIS guarantees be honored in useful fashion, however, the authors of clang and gcc have decided they'd rather claim that programs relying upon the decades-old CIS guarantees is "broken" than honor 40+ years of precedent.
is it enough to "just" put them in the same order at the very begining?
Yes, if you're careful as you've done above.
also, how to design the method header to accept it?
There are different ways to do this.
Here's an example, using the [ugly] equivalent of a c++ "base" class:
enum type {
FRAME,
BUTTON,
WHATEVER
};
struct geo {
int x;
int y;
int width;
int height;
enum type type;
};
struct frame {
struct geo geo;
};
struct button {
struct geo geo;
int updown;
};
struct whatever {
struct geo geo;
int what;
int ever;
};
void
frame_render(struct geo *geo)
{
struct frame *frm;
struct button *but;
struct whatever *what;
switch (geo->type) {
case FRAME:
frm = (struct frame *) geo;
frame_render_frame(frm);
break;
case BUTTON:
but = (struct button *) geo;
printf("x=%d y=%d updown=%d\n",geo->x,geo->y,but->updown);
frame_render_button(but);
break;
case WHATEVER:
what = (struct whatever *) geo;
printf("x=%d y=%d what=%d ever=%d\n",
what->geo.x,what->geo.y,what->what,what->ever);
frame_render_whatever(what);
break;
}
}
Here's a way to use a virtual function table:
enum type {
FRAME,
BUTTON,
WHATEVER
};
struct geo;
// virtual function table
struct virtfnc {
void (*calc)(struct geo *);
void (*render)(struct geo *);
};
struct geo {
int x;
int y;
int width;
int height;
enum type type;
struct virtfnc *fnc;
};
struct frame {
struct geo geo;
};
struct button {
struct geo geo;
int updown;
};
struct whatever {
struct geo geo;
int what;
int ever;
};
void
frame_render(struct geo *geo)
{
struct frame *frm = (struct frame *) geo;
// whatever
}
void
button_render(struct geo *geo)
{
struct button *but = (struct button *) geo;
// whatever
}
void
whatever_render(struct geo *geo)
{
struct whatever *what = (struct whatever *) geo;
// whatever
}
void
any_render(struct geo *geo)
{
geo->fnc->render(geo);
}
Here's a third way that uses a union. It is simpler but requires that the base struct be as large as the largest sub-class:
enum type {
FRAME,
BUTTON,
WHATEVER
};
struct frame {
...
};
struct button {
int updown;
};
struct whatever {
int what;
int ever;
};
struct geo {
int x;
int y;
int width;
int height;
enum type type;
union {
struct frame frame;
struct button button;
struct whatever what;
} data;
};
void
any_render(struct geo *geo)
{
switch (geo->type) {
case FRAME:
render_frame(&geo->data.frame);
break;
case BUTTON:
render_button(&geo->data.button);
break;
case WHATEVER:
render_whatever(&geo->data.what);
break;
}
}
UPDATE:
is this approach casting safe? eg. putting all into some array that is of the type frame* and then just accessing frame->geo? or would that cause any problems with later calls to free(..)?
No problem with free if allocations are done with the derived types (e.g. frame, button), but not the base type geo: malloc(sizeof(struct button)).
To have a simple array [of shapes], the union method would need to be used (i.e. all derived structs must have the same size). But, this would be wasteful if we had some subtype that used a lot more space than the others:
struct polyline {
int num_points;
int x[100];
int y[100];
};
This could still be done with methods #1 or #2 [where the subtype structs are of different sizes] with an indirect pointer array:
void
all_render(struct geo **glist,int ngeo)
{
for (; ngeo > 0; --ngeo, ++glist)
any_render(*glist);
}
Rather than an array of different shapes, I'd consider a [doubly] linked list. This allows the subtype structs to have different sizes. We'd add a struct geo *next element to struct geo. Then, we could do:
void
all_render(struct geo *geo)
{
for (; geo != NULL; geo = geo->next)
any_render(geo);
}
The list approach may be preferable, particularly if we add/remove shapes on a dynamic basis [or reorder them based on Z-depth].
Or, some shapes might contain others. So, we could add struct geo *children to struct geo. Then, it's easy to (e.g.) draw a containing box, then all the shapes within that box by traversing the children list. If we go for children, we may as well add struct parent *parent as well so each shape knows what shape contains it.
The "classical" method is to have a struct that contains a union of all possible objects and an enum that identifies which exactly object has been passed:
struct renderable {
enum {FRAME, BUTTON, WHATVERE, ...} type;
union {
struct frame frame;
struct button button;
struct whatever whatever;
....
} data;
};
After passing this struct to the renderer, use a switch on the type field to extract the coordinates, etc:
void renderer (renderable *obj, ...) {
...
switch(obj->type) {
case FRAME: x = obj->data.frame.x; ...; break;
case BUTTON: x = obj->data.button.x; ...; break;
...
}
...
}
It was reportedly this kind of monstrosity that encouraged Stroustrup to invent C++ :)
Edited
Another "classical" solution is to have a separate struct that has the dimensions and the position of any object:
struct geometry {
int x, y, width, height;
}
You can store this structure at the beginning of any object-specific struct and use a cast to gain access to it:
struct frame {
struct geometry geo;
// more stuff
};
struct frame frame = {....};
rendered((void*)&frame, ...);
In the renderer:
void renderer (void *obj, ...) {
...
struct geometry *geo = (struct geometry *)obj;
geo->x ...
}
The latter approach may be somewhat unsafe. To make it 100% safe, separate the geometry from the object-specific information and pass them to the renderer as two separate structs.
I have a couple structs typedef'd in my code, and I am using them frequently throughout my code. To improve readability, I would like my struct type to have its own text color, just like an int or char would. Is there a way to do this in gedit?
for example:
typedef struct
{
int m;
float v;
float x;
float y;
float z;
} body;
int n;
body x;
"int" will be colored blue in my theme, but "body" has the same color as a variable name.
this is making my code increasingly difficult to read.
thanks for any input!
This is what you're looking for:
Creating your own syntax highlighting in GEdit?
You just have to add a keyword that is the name of your struct.
I personally would try using a proper IDE instead of a text editor like gedit though.
I'm trying to make a struct that contains another struct with multiple arrays. I need to dynamically allocate those arrays too, so I think I need another pointer still.
int arraysize;
typedef struct Array{
int *size = arraysize;
unsigned int val[*size];
unsigned int x[*size];
unsigned int y[*size];
} Array;
typedef struct Image{
int height;
int width;
int max;
Array *data;
} Image;
OK, so once I finally figure that out, I still need to figure out how to dynamically allocate that memory using malloc. I'm totally lost there too. Any help at all would be greatly appreciated.
EDIT: more clarification:
I'm using the arrays to store three pieces of information that are all connected. Think of a chessboard, you could say knight E4, which tells you that on the 4th column of row E, there is a knight. If you started this process at A1 and ended at K10 you'd have a full chessboard right? The image struct is analogous to the chessboard, the Array is analogous to a list of a bunch of squares that compose the chessboard and the contents of those squares. (E.g. A1 null A2 knight a3 bishop etc...) Unfortunately, I don't know what kind of board will be passed through, it might be a 3x7 board or a 9x2 board etc. So I need to dynamically allocate the memory for those possibilities. Once I have the memory allocated I need to store information about the location and the contents of all of the "squares." Then I need to let a program pass through the height of the board, width of the board and the list of contents and I'd be done the hard part.
What you actually meant was:
typedef struct data {
unsigned int x;
unsigned int y;
unsigned int val;
} Data;
typedef struct image {
int height;
int width;
int max;
Data* data;
} Image;
and somewhere:
Image i;
i.height = 10;
i.width = 20;
i.data = malloc(sizeof(Data) * i.width * i.height);
...
// one of the ways how to access Data at 2nd row, 3rd column:
*(i.data + i.width * 1 + 2).val = 7;
...
free(i.data);
i.data = NULL;
But what you actually need is some good book ;)