a simpler way to get variables from structs within structs - c

It's been over a year since I last used C, so I'm pretty much back to basics.
I have this code as part of a larger file:
typedef struct
{
float ix;
float iy;
float iz;
} InitialPosition;
typedef struct
{
InitialPosition init;
} Particle;
void particle()
{
Particle p1 =
{
.init = { .ix = 10, .iy = 10, .iz = 10 },
};
glPointSize(10);
glBegin(GL_POINTS);
glVertex3f(p1.init.ix,p1.init.iy,p1.init.iz);
//glVertex3f( 0, 0, 0 );
glEnd();
}
It works/appears correctly with my particle being plotted onto an axis, but it seems like there must be a quicker way to feed the variables from the struct into the glVertex3f method.
On the off-chance it makes any difference I'm using openGL & glut.
Should I also be using pointers? (If so an example of use would be great.) Like I said it has been a while so any help appreciated.

Functions that take three separate parameters require that you break each value out. If you're going to be using these calls a lot, you have two ways to make it more convenient.
1) make a helper function:
void myglVertexParticle(Particle * apoint) { glVertex3f(init->ix, init->iy, init->iz) ; }
myglVertexParticle( & (p1.init)) ;
2) use an expansion macro:
#define PARTICLE3f(uuu) uuu.ix, uuu.iy, uuu.iz
glVertex3f( PARTICLE3f( p1.init)) ;
Most people are probably going to frown on the second choice from a style point of view, and a good optimizing compiler should make the first case run nearly as quickly as the second.

Related

Segfault with snprintf (unless I redefine the value the same way just before)

First of all please excuse me, I can't reproduce the problem, it comes from a big project and when I recover the functions one by one in a more minimalist file it suddenly works (without modifying almost anything) and I can't understand where it can come from.
First of all the project contains these structures:
typedef struct {
uint32_t x, y;
uint16_t w, h;
char* str;
} Text;
typedef struct {
uint32_t last_tick;
uint32_t delta_ms;
float delta;
float t_fps;
uint16_t fps;
} Clock;
I initialize the Text structure which is present in another structure that I will call Other from an initialization function for Other like this:
other->text_frame_rate = (Text){ 0,0,0,0, (char[8]){} };
It is supposed to contain text that looks like this FPS: 60.
Then I use snprintf to write the desired text to it in another function, like this:
void _render_frame_rate(Other* other, Clock clock)
{
snprintf(other->text_frame_rate.str, 8, "FPS: %d", clock->fps);
...
}
This _render_frame_rate function is itself called from another function which looks like this at the parameter level void Render_game(SDL_Renderer* renderer, Other* other, Clock* clock);
But I get a segfault unless I redefine the frame again in _render_frame_rate like this:
void _render_frame_rate(Other* other, Clock clock)
{
other->text_frame_rate = (Text){ 0,0,0,0, (char[8]){} }; // redefine and no problem
snprintf(other->text_frame_rate.str, 8, "FPS: %d", clock->fps);
...
}
And in this case, where the struct Text has been redefined it finally works.
I also checked with a printf("%p\n"); if the address of the pointer was always the same at initialization and at the display function and yes it remains the same.
I also specify that at no time is the text_frame_rate value used or modified elsewhere.
What do you think could be causing this behavior?
UPDATE: Thanks to #IanAbbott's hint I was able to solve the problem by dynamically allocating text_frame_rate like this:
other->text_frame_rate = (Text){ 0,0,0,0, NULL };
other->text_frame_rate.str = malloc(8);
Here is one erroneous example:
void init_other_text_frame_rate(Other *other)
{
other->text_frame_rate = (Text){0, 0, 0, 0, (char[8]){0}};
}
void render_frame_rate(Other* other, Clock clock)
{
snprintf(other->text_frame_rate.str, 8, "FPS: %d", clock->fps);
}
void foo(Other* other, Clock clock)
{
init_other_text_frame_rate(other, clock);
render_frame_rate(other, clock); // invalid!
}
The lifetime of the array of char pointed to by other->text_frame_rate.str expired when init_other_text_frame_rate(other, clock); returned to foo, so its use in the call to snprintf is invalid.

How to Wrap up a different types in a struct with void pointers

I had a plan earlier tonight, and now it's turning into a total mess.....I think I'm missing some fundamental concept.
Here's the idea:
I have to send some stuff over uart that looks like this (for example):
rpmL.txt="10"
vbatt.txt="20.4"
info.txt="Low Temperature"
battIcon.pic='8'
Simple enough, right?
Now, I have a bunch of different things that all have that same sort of format, but the only things that change are:
rpmL, vbatt, etc.
txt (this can be txt or pic)
10, 20.4, Low Temperature, 8 (this can be an int or a float or a string or an enumeration...You'll see the enum below )
So, my idea was, just make a typedef'd struct that has all these things that can change in it, and then make another struct that holds a bunch of those typedef'd 'things'.
anyway, here's the code, and i just want to increment things in different ways depending on it's type:
screen.h
typedef enum _ScreenType{
T_INT,
T_FLOAT,
T_CHAR,
T_TEMP_ICON,
T_BATT_ICON
} ScreenType;
typedef enum _tempIcon{
TEMP_LOW = 0,
TEMP_MED,
TEMP_HIGH,
//Add More Elements Up Here
TEMP_MAX_ELEMENTS
}TempIcon;
typedef enum _battIcon{
BATT_ZERO = 0,
BATT_TWENTY_FIVE,
BATT_FIFTY,
BATT_SEVENTY_FIVE,
BATT_FULL,
//Add More Elements Up Here
BATT_MAX_ELEMENTS
}BattIcon;
// Jam everything together so we can just pass the memeber of the following struct to the LCD TX function
typedef struct _packedStringVars{
ScreenType ScreenType; // I think I need this to achieve some crude polymorphism later on...
void* var; //I think I should do this because this can be a float, int or char*...
char* label; //This is always a string...nothing special about this.
}packedStringVars;
typedef struct{
packedStringVars temp;
packedStringVars wattage;
packedStringVars battPercent;
packedStringVars rpmL;
packedStringVars rpmR;
packedStringVars vbat;
packedStringVars tempIcon;
packedStringVars battIcon;
}mainScreenVariables;
and here's the source:
screen.c
#include "screen.h"
#include ..........Everything Else that You Would Expect.......
//This is where I'm trying to 'initialize' the values...I was doing *(int*) and *(float*), etc., but that went nowhere...
mainScreenVariables screenData = {
.temp = {T_INT,0,"temp"},
.wattage = {T_INT,0,"watts"},
.rpmL = {T_INT,0,"rpmL"},
.rpmR = {T_INT,0,"rpmR"},
.vbat = {T_FLOAT,0,"vbat"},
.tempIcon = {T_TEMP_ICON,(TempIcon*)TEMP_LOW,"p1"},
.battIcon = {T_BATT_ICON,(BattIcon*)BATT_FULL,"battIcon"}
};
static void updateValues(void)
{
// As you can see, now i'm typecasting them as I'm using them, which feels all kinds of wrong and also, as it turns out, doesn't even work! surprise surprise....
*(int*)screenData.temp.var++;
*(int*)screenData.wattage.var++;
*(int*)screenData.battPercent.var++;
*(int*)screenData.rpmL.var++;
*(int*)screenData.rpmR.var++;
*(float*)screenData.vbat.var+=0.1;
*(TempIcon*)screenData.tempIcon.var++;
*(ScreenType*)screenData.battIcon.var++;
}
There's more code to make sure the enumerations don't grow beyond their bounds and so forth, but really, all I want to do is set this conceptual object, and send it to the the UART, with a function signature that looks like this:
void ForChristsSakesJustSendTheDamnString(screenData * dat);
I'm sure there's some better, idiomatic way to do this. This is totally out of control and just feels wrong.
Thanks!

CSFML Vertex Array and drawing

It's been a few weeks i've been working a project for my school and I now need to work on particles. I've been looking at vertices and it looks like to be a good way to make them.
I've started by trying to print at least one vertex on the screen and to print it, but I don't know what I'm doing wrong.
CSFML is a very restricted library as not many people use it, so trying to find SFML examples and to figure out the derivates of the functions to C is quite hard and giving me some troubles.
Here's my code :
{
sfVertex a;
sfVector2f apos = {200, 100};
a.color = sfRed;
a.position = apos;
sfVertexArray *array = sfVertexArray_create();
sfVertexArray_setPrimitiveType(array, sfPoints);
sfVertexArray_append(array, a);
sfRenderWindow_drawVertexArray(window, array, 0);
}
In this example, I'm trying to create a vertex, give it a position, a color, and then create a vertex array that takes point vertices and to append my vertex to the vertex array. I think the only problem here is to print it on the screen, as sfRenderWindow_drawVertexArray(window, array, 0); doesn't print anything, and if I put the render state to 1 my program just crashes before even opening my window.
I tried to find examples and explanations about this function but I'm pretty much lost now.
I think your error was that you did not set sfPoints in your code. Here is a simple code that draws 4 points.
#include <iostream>
#include <SFML/Graphics.hpp>
int main(){
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
sf::VertexArray vertexArray (sf::Points, 4);
vertexArray[0].position = sf::Vector2f(10, 10);
vertexArray[1].position = sf::Vector2f(10, 20);
vertexArray[2].position = sf::Vector2f(20, 10);
vertexArray[3].position = sf::Vector2f(20, 20);
// Set colour for all vertices
for(int i = 0; i < 4.; i++){
vertexArray[i].color=sf::Color::Yellow;
}
window.clear();
window.draw(vertexArray);
window.display();
}
return 0;
}

pass struct of arrays into function

I am trying to pass a struct of 2D arrays and to do calculations on them.
typedef struct{
float X[80][2];
float Y[80][2];
float Z[80][2];
int T[80][2];
int K[80];
} STATS;
void MovingAverage(STATS *stat_array, int last_stat) {
//Average = Average(Prev) + (ValueToAverage/n) - (Average(Prev)/n)
stat_array->**X**[last_stat][0] = stat_array->**X**[last_stat][0] +
(stat_array->**X**[last_stat][1] / stat_array->T[last_stat][0]) -
(stat_array->**X**[last_stat][0] / stat_array->T[last_stat][0]);
}
calling the function:
MovingAverage(*stat_array, last_stat);
My question is:
how do I access in a generic way to X Y and Z inside MovingAverage function?
Edit:
void MovingAverage(STATS *stat_array, int last_stat, (char *(array_idx)) {
//Average = Average(Prev) + (ValueToAverage/n) - (Average(Prev)/n)
stat_array->**array_idx**[last_stat][0] =
stat_array->**array_idx**[last_stat][0] +
(stat_array->**array_idx**[last_stat][1] /
stat_array->T[last_stat][0]) -
(stat_array->**array_idx**[last_stat][0] /
stat_array->T[last_stat][0]);
}
I know it won't work, but just to demonstrate my willings,
Somebody here (not me) could probably come up with some preprocessor magic to do what you're asking, but that is a solution I would not pursue. I consider it bad practice since macros can quickly get hairy and tough to debug. You can't have "variables" inside your source code, if that makes sense. During the build procedure, one of the first things that runs is the preprocessor, which resolves all your macros. It then passes that source code to the compiler. The compiler is not going to do any text substitutions for you, it cranks on the source code it has. To achieve what you want, write a function that operates on the type you want, and call that function with all your types. I'd change your MovingAverage function to something like this:
void MovingAverage(float arr[80][2], const int T[80][2], int last_stat)
{
arr[last_stat][0] = ... // whatever calculation you want to do here
}
int main(void)
{
STATS stat_array;
int last_stat;
// .. initialize stat_array and last_stat
// now call MovingAverage with each of your 3 arrays
MovingAverage(stat_array.X, stat_array.T, last_stat);
MovingAverage(stat_array.Y, stat_array.T, last_stat);
MovingAverage(stat_array.Z, stat_array.T, last_stat);
...
return 0;
}

Any jump with return instruction in C?

I have multiple locations in my code where I want to be able to jump to one specific location and return to where I was before.
A function calls provides that control flow but is not an option for me as I want the code I branch to to access a number of variables and passing all of them as arguments to the function call wouldn't be practical or efficient.
And the goto statement is only built to take a label, i.e. expected to be a one-way ticket.
Currently I am achieving what I need with the following:
void *return_addr;
int x,y;
...
return_addr=&&RETURN_0;
goto SOMEWHERE;
RETURN_0:
...
x+=1;
...
return_addr=&&RETURN_1;
goto SOMEWHERE;
RETURN_1:
...
SOMEWHERE:
y=x;
...
goto *return_addr;
Is there something more elegant and less cumbersome?
Is there something more elegant and less cumbersome?
You are obviously using GCC, as the computed goto statement is a GCC extension. With GCC we can use a nested function and access local variables without needing to pass them as arguments:
{
int x, y;
void SOMEWHERE()
{
y = x;
//...
}
//...
SOMEWHERE();
//...
x += 1;
//...
SOMEWHERE();
//...
}
Let's have the variables collected in a structure:
struct data_t {
int a;
int b;
/* and so on */
int x;
int y;
};
Let's have the repeated code defined in a function:
void func(struct data_t* data) {
data->y = data->x;
/* and so on */
}
Let's have the function used:
struct data_t data = {1, 2, ..., 24, 25};
func(&data);
data.x += 1;
func(&data);
/* and so on */
C has setjmp() / longjmp(), which can support what you describe. Do not use them. Even more, however, do not rely on your current approach, which is not standard C, and which is terribly poor form.
What you describe is what functions are for. If you have a lot of data that you must share between the caller and callee, then either
record them in file-scope variables so that both functions can access them directly, or
create one or more complex data types (presumably structs) with which to hold and organize the data, and give the callee access by passing a pointer to such a struct.
A state machine can be written like this:
typedef enum { start, stop, state1, ... } state;
state s = start;
while (s != stop) {
switch (s) {
case start:
do_stuff; // lots of code
// computed goto
s = cond ? state23 : state45;
break;
...
Need a call stack?
state stack[42]; int sp=0;
...
do_stuff;
stack[sp++] = state33;
s = state45; // call
break;
case state33:
case state45:
do_processing; // some code
s = stack[--sp]; // ret
break;
You should only do this after you benchmark your time-critical code sections and find that the normal function call mechanism is indeed the bottleneck.

Resources