Can I access my union using the arrow operator (->)? - c

I would like to know whether or not I can use the arrow operator in my union and I don't have access to my build environment.
Let's say that I have the following union
union max30205_raw_data {
struct {
uint8_t lsb;
uint8_t msb;
};
struct {
uint16_t magnitude_bits:15;
uint16_t sign_bit:1;
};
uint16_t uwrd;
int16_t swrd;
};
I will fill the content of the union in the following way, but I was wondering whether the access to the union member msb and lsb is correct?
int32_t max30205_read_reg16_WithDefUnion(char reg, max30205_raw_data *p_unionRawData) {
char aux[] = {0,0}
int32_t error;
if (reg == MAX30205_REG_TEMPERATURE || reg == MAX30205_REG_THYST_LOW_TRIP || reg == MAX30205_REG_TOS_HIGH_TRIP) {
error = twi_max30205_read(&myMax30205Instance,max30205Address,reg,&aux,sizeof(aux));
if(error == 0){
p_unionRawData->msb = aux[0];//IS THIS RIGHT IN C?
p_unionRawData->lsb = aux[1];//IS THIS RIGHT IN C?
}
}
return error;
}
I will call max30205_read_reg16_WithDefUnion()as
int16_t max30205MeasureTemperatureWithDefUnion(void) {
char regT = MAX30205_REG_TEMPERATURE;
max30205_raw_data rawTemp;
rawTemp.msb = 0;
rawTemp.lsb = 0;
rawTemp.swrd = 0;
int16_t temperatureValue = 0;
if (max30205_read_reg16_WithDefUnion(regT,&rawTemp) ==0)
temperatureValue = rawTemp.swrd;
return temperatureValue;
}

Yes. -> works with both pointers to structs and pointers to unions.

Related

Variabe type for variable inside function

I'm having different different types of structs, which are going to be passed to a function which performs the same tasks on them.
int menu_parameter_arrow_print(game_setting_identifier* identifier, controller_direction direction, uint8_t position)
{
if((position > setting->alternatives_number) || position < 0)
{
#ifdef OLED_PRINT_DEBUG_ENABLE
OLED_debug_print("Out of bounds");
#endif
return RETURN_VALUE_FAILURE;
}
else
{
switch ((int)*identifier)
{
case ((int) GAME_SETTING_ANALOG):
game_setting_analog* setting = (game_setting_analog*)&identifier;
case ((int) GAME_SETTING_TOGGLE):
game_setting_toggle* setting = (game_setting_toggle*)&identifier;
case ((int) GAME_SETTING_VALUE):
game_setting_value* setting = (game_setting_value*)&identifier;
}
This function gives a conflicting type-error
The operations performed on the structs are the same, but the structs contains different types of members:
struct game_setting_analog
{
//Identifier for the game-setting type:
game_setting_identifier identifier;
//Alternatives:
char* alternatives[4];
};
typedef struct game_setting_value game_setting_value;
struct game_setting_value
{
game_setting_identifier identifier;
uint8_t* alternatives[6];
uint8_t alternatives_number;
};
typedef struct game_setting_toggle game_setting_toggle;
struct game_setting_toggle
{
//Identifier for the game-setting type:
game_setting_identifier identifier;
toggle_state* alternatives[2];
};
typedef struct game_setting_difficulty game_setting_difficulty;
struct game_setting_difficulty
{
game_setting_identifier identifier;
char* alternatives[3];
};
Actions will be performed on the 'alternatives'-member of the structs, even though these members are of different types.
Is there a solution to doing this without having to use one if-statement for each identifier?
Edit: With a modification to the switch-case, I'm able to get the initialization compiled. The variables inside the switch-scope is however not visible to the rest of the function
int menu_print_parameter_line(game_setting_identifier* identifier, controller* C, uint8_t position)
{
uint8_t next_position = position;
controller_direction previous_direction = C->joystick.generalDirection;
if ((identifier == NULL) || (C == NULL) || (position == NULL))
{
return -1;
}
switch((int) identifier)
{
case ((int) GAME_SETTING_ANALOG):
{
game_setting_analog* setting = (game_setting_analog*)identifier;
uint8_t alternatives_number = 4;
}
break;
case ((int) GAME_SETTING_TOGGLE):
{
game_setting_toggle* setting = (game_setting_toggle*)identifier;
uint8_t alternatives_number = 2;
}
break;
case ((int) GAME_SETTING_VALUE):
{
game_setting_value* setting = (game_setting_value*)identifier;
uint8_t alternatives_number = setting->alternatives_number;
}
break;
default:
{
return -1;
}
break;
}
#ifdef MENU_PARAMETER_ASSIGNMENT_DEBUG
OLED_debug_print("before switch-case");
#endif
switch (previous_direction)
{
case LEFT:
next_position -= 1;
if(next_position <= 0)
{
next_position = alternatives_number;
}
I personally don't like the inheritance model that depends on the first member of the structure, like the BSD socket library is using. Basically you are just trying to implement std::variant from c++ in C.
Is there a solution to doing this without having to use one if-statement for each identifier?
The object-oriented concept of interface works very nice and I believe is applicable in this case. It takes some C discipline to write it, but it works like a charm and you could be looking for it here.
I copied your definitions from which I removed typedefs because I don't like them:
struct game_setting_analog {
char* alternatives[4];
};
struct game_setting_value {
uint8_t* alternatives[6];
uint8_t alternatives_number;
};
struct game_setting_toggle {
toggle_state* alternatives[2];
};
struct game_setting_difficulty {
char* alternatives[3];
};
Let's first implement the interface abstraction with a function pointer that allows to get the alternatives number:
// forward definition
struct game_setting_s;
// the virtual table for game_settings
struct game_setting_vtable_s {
uint8_t (*get_alternatives_number)(struct game_setting_s *t);
// TODO: add other members, constructor, copy constructor, destructor, etc.
};
// represents any game_setting
// exposes a public interface to access and manipulate a game_setting
struct game_setting_s {
// the vtable is const, so it can save RAM
const struct game_setting_vtable_s *v;
// this is a pointer to private settings data
void *data;
};
// accessor for less (or more ;) typing
static inline
uint8_t game_setting_get_alternatives_number(struct game_setting_s *t) {
// alternative you could pass t->data to the function, I pass it all
// so that functions can modify the t->data member
// and also so that advanced functions usages can use like container_of macros
return t->v.get_alternatives_number(t);
}
Then you need to provide the virtual tables for each of the types. The definitions can be in separate types, so you can have a separate .c/.h file pair for each of the type, just exposing public interface.
// game_setting_analog --------------------
static
uint8_t game_setting_analog_get_altenatives_number(struct game_setting_s *t)
{
return 4;
}
const struct game_setting_vtable_s game_setting_analog_vtable = {
.get_alternatives_number = game_setting_analog_get_altenatives_number,
};
// game_setting_toggle --------------------
static
uint8_t game_setting_toggle_get_altenatives_number(struct game_setting_s *t) {
struct game_setting_toggle *data = t->data;
return data->alternatives_number;
}
const struct game_toggle_vtable_s game_setting_toggle_vtable = {
.get_alternatives_number = game_setting_toggle_get_altenatives_number,
};
// and so on...
Then your function takes just the interface and is very clear without any switch case:
int some_function_that_needs_to_know_which_setting_is_passed(struct game_setting_s *s) {
int number_of_alternatives = game_setting_get_alternatives_number(s);
}
Remember to construct the interface object properly and watch who owns the memory of the object. Let's construct a toggle and call out function:
struct game_settting_toggle memory;
// your function to initialize the toggle
game_setting_toggle_intialize(&memory);
// the interface is constructed with the proper vtable
// and a pointer to proper memory region with the data
struct game_setting_s any_setting = {
.vtable = game_setting_toggle_vtable,
.data = &memory,
};
// the initailize function could be in interface too
// so you would just call game_setting_initialize(&any_setting);
// with usage of dynamic allocation, you can just ex.
// struct game_setting_s *any_setting = game_setting_new_toggle();
// and write proper object-oriented factories
// finally call our function.
some_function_that_needs_to_know_which_setting_is_passed(&any_setting);
Case labels do not provide scopes for variables. All three setting variables within the switch have different types which are the conflicts the compiler. Use brackets to define scopes:
switch ((int)*identifier)
{
case ((int) GAME_SETTING_ANALOG):
{
game_setting_analog* setting = (game_setting_analog*)&identifier;
}
case ((int) GAME_SETTING_TOGGLE):
{
game_setting_toggle* setting = (game_setting_toggle*)&identifier;
}
case ((int) GAME_SETTING_VALUE):
{
game_setting_value* setting = (game_setting_value*)&identifier;
}
}
Also, you're not breaking in the cases, so the code in all three cases are run if ((int)*identifier == (int) GAME_SETTING_ANALOG)

Why am I getting a type error when trying to use a struct from a header in my .c file?

I really don't understand what is happening here. I'm trying to access members of a struct in a .c file, but it's giving an 'error-type' when I try to access the struct variable. Anybody have any idea what's going on here?
CPU.h Header file:
#ifndef _CPU_H
#define _CPU_H
#include <stdint.h>
typedef struct cpu_registers
{
union
{
struct
{
uint8_t f;
uint8_t a;
};
uint16_t af;
};
union
{
struct
{
uint8_t c;
uint8_t b;
};
uint16_t bc;
};
} cpu_registers;
#endif /* _CPU_H */
CPU.c file:
#include "CPU.h"
cpu_registers regs;
regs.af = 0xFFFF;
Here are the errors upon compilation with clang:
CPU.c:4:1: error: unknown type name 'regs'
regs.af = 0xFFFF;
^
CPU.c:4:5: error: expected identifier or '('
regs.af = 0xFFFF;
^
2 errors generated.
You can declare and initialize global variables outside of functions, but you cannot do anything else with them.
So, you could do this:
cpu_registers regs = { .af = 0xFFFF };
However, do note that this will not work:
int val = 0xFFFF;
cpu_registers regs = { .af = val };
And - maybe a bit surprisingly - not this either:
const int val = 0xFFFF;
cpu_registers regs = { .af = val };

expected expression before '!=' token... Where I'm wrong?

enum LIVELLI_EMERGENZA {
LIV_EME_UNO = 0x0001,
LIV_EME_DUE = 0x0002,
LIV_EME_TRE = 0x0003
};
typedef struct Emergenza {
int Tipo;
short Livello;
} Emergenza;
void TrovaEmergenze()
{
if(INPUT_GET(IN_FUNGO_EMERGENZA)) {
Emergenza.Tipo |= EME_FUNGO_PREMUTO;
Emergenza.Livello |= LIV_EME_UNO;
}
if((INPUT_GET(IN_FC_CARTER_LAMA))){
Emergenza.Tipo |= EME_CARTER_LAMA_APERTO;
Emergenza.Livello |= LIV_EME_DUE;
}
}
char EmeLivello1()
{
if((Emergenza.Livello & LIV_EME_UNO) != 0)
return 1;
return 0;
}
Having evaluated the mask emergenza.livello I'm going to check it with & LIV_EME_UNO. If it is different from 0, this means that the bits in the mask is high; but I get the error "expected expression before '!=' token".
In your code, Emergenza is essentially a datatype, not a variable. You need to have a variable of that type to use the member access operator .
To make Emergenza a variable instead of a datatype do this:
struct Emergenza {
int Tipo;
short Livello;
} Emergenza;
In summary, remove the typedef.

Error when compiling for MicroChip 'invalid operands to binary =='

static int handle_put_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt,coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
{
if (inpkt->payload.len == 0)
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN);
if (inpkt->payload.p[0] == '1')
{
light = '1';
UARTWrite(1,"ON\n");
return coap_make_response(scratch, outpkt, (const UINT8_VAL *)&light, 1, id_hi, id_lo, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN);
}
else
{
light = '0';
UARTWrite(1,"OFF\n");
return coap_make_response(scratch, outpkt, (const UINT8_VAL *)&light, 1, id_hi, id_lo, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN);
}
}
This is my code and i am getting error on line no.5 . The struct is defined as
typedef struct
{
coap_header_t hdr;
coap_buffer_t tok;
uint8_t numopts;
coap_option_t opts[MAXOPT];
coap_buffer_t payload;
} coap_packet_t;
typedef struct
{
const UINT8_VAL *p;
size_t len;
} coap_buffer_t;
I am getting the following error when i try to compile using Microchip c30 compiler which is primarily C compiler.
Error :- error: invalid operands to binary ==
Please HElp me !!
Try using the Val member of UINT8_VAL for comparison:
inpkt->payloadp[0].Val == '1'

Struct initialization problem in C

I seem to be having a problem setting the values of an array inside a structure with a meaningless error spat out of the compiler:
expected primary-expression before '{' token
I understand that a structure must "exist" to accept values, and it exists as a pointer to one. I would like you to explain to me what i am doing wrong and how to achieve my objective.
struct EventCheckData {
unsigned long refresh_time;
unsigned long last_execution_ms; //Can also serve to delay at startup
byte signal_type;
};
struct ClockData {
struct EventCheckData event_array[4];
byte event_count;
unsigned long last_absolute_time;
UISignal *warning_signals;
};
void ResetClock(UISignal *warning_signal, struct ClockData *clock_data, unsigned long absolute_time) {
if(SignalCheckValue(warning_signal, RESET_CLOCK, 1)) {
extern volatile unsigned long timer0_overflow_count;
timer0_overflow_count = 0;
clock_data->last_absolute_time = absolute_time;
clock_data->event_count = 3;
(clock_data->event_array)[0] = { .refresh_time = 3000UL, .last_execution_ms = 0UL, .signal_type = WATER_PUMP_ON};
// clock_data->event_array[1] = {10000UL, 0UL, EXPORT_LOG};
// clock_data->event_array[2] = {100000UL, 0UL, EXTERNAL_CONNECTION};
SignalSet(warning_signal, RESET_CLOCK, 0);
}
}
Thank you
Paulo Neves
(clock_data->event_array)[0] = { .refresh_time = 3000UL, .last_execution_ms = 0UL, .signal_type = WATER_PUMP_ON}; is not initialization. It is assignment.
And you cannot use initializer syntax in assignment.
With C99, you should be able to use a compound literal, like
(clock_data->event_array)[0] = (struct EventCheckData){ .refresh_time = 3000UL, .last_execution_ms = 0UL, .signal_type = WATER_PUMP_ON};
The way you are assigning it looks like an initializer. You need assignment, try a compound literal:
clock_data->event_array[0] = (struct EventCheckData){ .refresh_time = 3000UL, ...};
Without any C99 stuff you can simply use:
void ResetClock(UISignal *warning_signal, struct ClockData *clock_data, unsigned long absolute_time) {
if(SignalCheckValue(warning_signal, RESET_CLOCK, 1)) {
extern volatile unsigned long timer0_overflow_count;
timer0_overflow_count = 0;
clock_data->last_absolute_time = absolute_time;
clock_data->event_count = 3;
{
struct EventCheckData a[]={ {3000UL, 0UL, WATER_PUMP_ON},
{10000UL, 0UL, EXPORT_LOG},
{100000UL, 0UL, EXTERNAL_CONNECTION}};
memcpy(clock_data->event_array,a,sizeof a);
}
SignalSet(warning_signal, RESET_CLOCK, 0);
}

Resources