better usage of structures in embedded field - c

I'm bit new to c programming and i want to learn and use the structure facility in C programming.
I'm working in the embedded programming field of 8bit controllers.
I have a situation in which
objective:
To set time and date or more things.
To get time and date or more things.
Problem: I have two source files main.c and set_get.c i have a struct
varaible in main.
Aim : to set and get rtcc values from registers in pic18 series controllers and to create a test platform.
main()
{
struct data
{
unsigned char hour=10;
unsigned char date=20;
} entry;
entry=set_time_date(entry);
entry=get_time_date();
while(1);
}
and in set_get.c
i have two functions
//here struct parameter will be the input from main.c
struct data
{
unsigned char hour=10;
unsigned char date=20;
};
struct set_time_date(struct x)
{
struct data p1;
p1.hour=x.hour;
p1.date=x.date;
//do set hour register with p.hour value
//do set date register with p.date value
return(p1);
}
struct get_time_date(void)
{
struct data p1;
p1.hour= do read from hour register;
p1.date= do read from day register;
return(p1);
}
I would like to have your inputs on this and correct me if i have made any mistakes in the following pattern.I have done in this method so as to reduce global structs.
And im keenly waiting your review on this piece of code.Correct me if im wrong
Regards
Arookie

Note, there is a rich library of time functions included in C89, C99, etc.
time_t time (time_t *Current_Calendar_Time);
clock_t clock (void);
char *ctime (const time_t *Calendar_Time);
Just to name a few. But in keeping with the theme of what you have already done...
First, This code segment will not compile. Assignments cannot be made inside the struct definition:
struct data
{
unsigned char hour=10;
unsigned char date=20;
};
However, once the struct is defined, you can make assignments to each individual member (see examples in code example below) Or you can make a block assignment, like this:
//Note, I am using a typedef variation of your original for illustration:
typedef struct data{
unsigned char hour;
unsigned char date;
} data;
//make block assignment here:
// hour date
struct data a = {0x34, 0xA5};
Next, passing a pointer to struct is sometimes better than passing the struct itself. i.e. when volume of data is large, passing address (~4bytes) is preferable to passing possibly hundreds of bytes. (For the size of your struct, it is really not a concern) My examples will use pointers:
For readability, create a type:
//you originally used unsigned char for member types. I changed it to
//accommodate puctuation,as often, timestrings and datestrings use
//puncutation such as : or /
//The unsigned version is below this one...
#define TIME_LEN 20
#define DATE_LEN 20
typedef struct {
char hour[TIME_LEN];
char date[DATE_LEN];
} DATA;
//use DATA to create the other instances you need:
DATA entry, *pEntry;
//Your function prototypes become:
void set_time_date(DATA *x); //no need to return time in set function
DATA * get_time_date(void);
//In main, initialize pointer to struct this way:
int main(void)
{
pEntry = &entry;//initialize pointer pEntry to address of entry
sprintf(pEntry->date , "%s", "12/23/2014");
sprintf(pEntry->hour , "%s", "10:12:13");
set_time_date(pEntry);
pEntry = get_time_date();
return 0;
}
void set_time_date(DATA *x)
{
sprintf(pEntry->date, "%s", x->date);
sprintf(pEntry->hour, "%s", x->hour);
}
DATA * get_time_date(void)
{
sprintf(pEntry->date, "%s", "01/23/2014");
sprintf(pEntry->hour, "%s", "10:10:00");
return pEntry;
}
using unsigned char
In this section, changes have been made to accommodate minimization of global struct. By creating a typedef of the struct, say in a header file, you can then simply use DATA * where needed to create a local instance of the struct, and pass it as an argument...
//Your function prototypes become:
void set_time_date(DATA *x); //no need to return time in set function
DATA * get_time_date(DATA *x); //Edited to include argument
//In main, initialize pointer to struct this way:
int main(void)
{
//Create local instance of DATA:
DATA entry={0}, *pEntry;
pEntry = &entry;//initialize pointer pEntry to address of entry
pEntry->date = 0x12;
pEntry->hour = 0x23;
set_time_date(pEntry);
pEntry = get_time_date(pEntry);
//print results showing values of both pEntry and entry
printf("pEntry->date: 0x%x\n", pEntry->date);
printf("entry.date: 0x%x\n", entry.date);
printf("pEntry->hour: 0x%x\n", pEntry->hour);
printf("entry.hour: 0x%x\n", entry.hour);
//After the assignment: "pEntry = &entry;" (above)
//pEntry is pointing to the the same location
//in memory as the start of entry. (this is the reason for that assignment)
//Every subsequent assignment you make to pEntry, is also being
//written to entry, without explicitly having to
//write: entry.date = 0x23 etc. (indeed, it is the same location
//in memory you are writing to)
return 0;
}
void set_time_date(DATA *x)
{
x->date = 0xBC;
x->hour = 0x45;
}
DATA * get_time_date(DATA *pX)
{
//Commented following two lines, passed in as argument:
//DATA x, *pX; //now passed in as argument
//pX = &x;//initialize pointer pX to address of x
pX->date = 0x23;
pX->hour = 0x34;
return pX;
}
Produces following output

Related

How to write after the end of the already initialized struct?

I have a struct initialized on a stack, and i want to write data in memory right after the struct and make a pointer inside a struct point to that data.
I know it is achievable on the stack/heap with uninitialized structure using malloc(sizeof(struct) + additional size) or alloca(). but can i perform initialization of a data after the struct is already initialized on the stack? and can i perform this initialization inside a initializator function?
Simple example:
struct TEST {
wchar_t* itest;
};
void init_struct(struct TEST* test) {
// point to the end of the struct
char* walk_ptr = (char*)test + sizeof(test);
test->itest = (wchar_t*)walk_ptr;
// initialize data after the struct
...
}
int main(void) {
struct TEST test;
init_struct(&test);
return 0;
}
You could do this by embedding the structure inside another structure to reserve memory for the extra data:
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test);
…
}
However, the code in init_struct adds an incorrect size, sizeof(test), to the pointer. You likely wanted to add sizeof (struct Test), or, equivalently, sizeof *test, since you want to get past the struct TEST that test points to, not past a struct TEST * that test is.
However, even adding the correct size of the structure would not guarantee strictly conforming C code, since C implementations may insert padding between structure members. Properly we would add the offset of the data member. To do that, we nwould eed to give the structure a tag and then either make the structure definition visible to init_struct or pass the offset to init_struct. However, it is easier just to pass the address of the extra data:
void init_struct(struct TEST *test, wchar_t *data)
{
test->itest = data;
}
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test, S.data);
…
}
Of course, a pointer can point anywhere, and there is no apparent reason the data should be immediate after the structure, so we can disconnect them:
int main(void)
{
struct TEST test;
wchar_t data[NumberOfElements];
init_struct(&test, data);
…
}

C function pointer and struct

I am new to C function pointer and structure. Here is what I want to achieve say there is a structure
typedef struct gfcrequest_t gfcrequest_t;
Later on this struct will be used to point to a function and the function will be called
gfcrequest_t *gfc_create();
gfr = gfc_create();
gfc_set_server(&gfr, server);
gfc_set_port(&gfr, port);
So are the following codes correct to initiate and later on I could add elements like server name and port number?
gfcrequest_t *gfc_create() {
struct out {
struct hostent *server;
int portno;
};
return out;
}
void gfc_set_port(gfcrequest_t **gfr, unsigned short port) {
gfr.portno = port;
}
void gfc_set_server(gfcrequest_t **gfr, const char *server) {
gfr.server = gethostbyname(server);
}
thats not how you do pointers to function.
to declare a pointer to function you do this:
if your function is:
int ft_somefink (int a, int b);
the pointer should be:
struct s_structure;
typedef struct s_structure t_structure;
struct s_structure
{
int (*funct)(int, int);
};
the typedef is there to simplify syntax.
its just an alias to avoid having to type "struct" everytime you use the structure.
you initialize it like so:
int main ()
{
t_structure name;
name.funct = &ft_somefink;
}
And call it like so:
int main()
{
t_structure name;
int a;
int b;
a = 1;
b = 2;
name.funct = &ft_somefink;
...
name.funct(a, b);
}
or like so if you pass the structure as pointer, it should look like this:
the main:
int main ()
{
t_structure *name;
...
function_somthing_useful(&name);
}
and the function:
void function_something_useful(t_structure **name)
{
if (!(*name = malloc(sizeof(t_structure))))
{
fprintf(stderr, "malloc error, not enough memory or swap nvm\n")
return ;
}
name->funct = &ft_somefink;
}
And, obviously, you call it then by:
name->funct(a, b);
note that you can malloc in main, doesnt matter. the idea to pass just the pointer is to avoid having to copy the whole structure everytime you pass it to a function.
the difference between . and -> operator is a dereferencing, but that would be another subject.
also i think it is better to pass the function as a pointer, instead of the whole thing because that might imply copying all of the functions instructions. not 100% sure of that tho... or rather depends on the system.
on linux reads are suposed to be "atomic", which, in my experience includes what happens on the stack. couldnt speak about other systems tho...
definitely could use someone to fill in the blanks here...

passing array of variables to function in C

I have a C function which needs a large amount of variables to be passed, so I came to the idea of "packing" them all in a single array (matrix of variables). The point is, these variables are of a very different type, some int, some arrays (strings and vectors), and many of them float. Is there a way to leave unspecified the type of data stored into the matrix? (I unsuccessfully explored the void "data type")
The elements of an array are always of a single type, that's the point.
Collecting variables of multiple types is the job for a structure, i.e. a struct.
This is a quite common way to solve this particular problem. If the structure becomes large, you might find it convenient to pass a pointer to an instance of it, rather than copying the entire thing in the call.
You can use va_list but struct is the best way to do it
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
enum type {
INT,
FLOAT,
PCHAR,
};
struct any_type {
enum type type_;
union {
int int_;
float float_;
char* pchar_;
};
};
#define MYSIZE 10
void process(size_t size, struct any_type* array)
{
for(int i = 0; i < size; i++) {
switch(array[i].type_) {
case INT :
printf("INT: %d\n", array[i].int_);
break;
case FLOAT :
printf("FLOAT: %f\n", array[i].float_);
break;
case PCHAR :
printf("PCHAR: %s\n", array[i].pchar_);
break;
default:
printf("UNKNOWN TYPE PROVIDED\n");
break;
}
}
}
int main(int argc, char *argv[])
{
struct any_type *array;
array = malloc(MYSIZE*(sizeof(struct any_type)));
array[0].type_ = INT;
array[0].int_ = 10;
array[1].type_ = FLOAT;
array[1].float_ = 2.5;
array[2].type_ = PCHAR;
array[2].pchar_ = "hello char";
process(3, array);
return 0;
}
You can extend type and union as needed. However using nameless unions require -std=c11.
Expanding on my comment above:
Needing to pass a large number of parameters1 to a function can be a sign that there is a problem in your design - your function may be trying to do too many things at once, and you would be better off refactoring it into several smaller functions, each of which only takes a subset of the parameters.
Assuming that's not the case, how are your parameters logically related to each other? Can they be considered attributes of a single data item? For example, a person may be described by the following attributes: surname, given name, birth date, sex. These can be collected together into a single struct type such as
#include <time.h>
struct person {
char *surname;
char *name;
struct tm birthdate; // struct tm defined in time.h
char sex;
};
void write_to( struct person *p )
{
p->surname = strdup( "McGillicuddy" );
p->name = strdup( "Aloysius" );
p->sex = 'M';
p->birthdate.tm_year = 32; // tm_year starts at 1900, so this is 1932
p->birthdate.tm_mon = 11; // december
p->birthdate.tm_day = 1;
};
int main( void )
{
struct person p;
...
write_to( &p );
...
}
Note that members of struct types can themselves be struct types - struct tm is a type defined in time.h that specifies a datetime value using multiple attributes.
Some notes on syntax:
When you want to access a member of a struct instance, use the . operator. When you want to access a member of a struct through a pointer, use the -> operator. In the function write_to, p is a pointer to struct person, so to access each member of p we use ->. The birthdate member is an instance of struct tm, not a pointer, so we use the . operator to access each member of birthdate.
p->m is equivalent to (*p).m.
Like I said in my comment, you should not collect otherwise unrelated items into a struct type just to reduce the number of parameters being passed to a function. They should all be attributes of a more complex type. Some other examples of what I mean:
// A node in a list
struct node {
data_t data; // for some data type data_t;
struct node *next;
struct node *prev;
};
// A street address
struct addr {
char *number; // to handle things like 102A, 102B
char *street;
char *city;
char state[3];
char *zip;
};
It's possible that you're really passing only a couple of distinct data items to your function, each of which is composed of a lot of different attributes. Take a step back and look at your variables and see how they relate to each other.
"Large" depends on context, and of course there are always exceptions to any rule, but in general passing more than 7 distinct, unrelated parameters is a sign you may need to refactor your function into several smaller functions.

How to use different datatype variable based on condition?

I have following two structure
typedef struct {
int day;
char action [10];
}DataType1;
and
typedef struct {
int day;
char action [50];
}DataType2;
Now i have to use only one structure data type based on some condition. I have done something like this
void *ptr;
DataType1 var1;
DataType2 var2;
if (validCondition == true)
{
ptr = &var1;
}
else
{
ptr = &var2;
}
//Used ptr in remaining code
But using this code i fill that may be there is some design flew in my code that's why i need this type trick but anyway i need that. I thought some different way also but i have doubt how it works
if (validCondition == true)
{
#define GENERIC_TYPE DataType1;
}
else
{
#define GENERIC_TYPE DataType2;
}
GENERIC_TYPE myVar;
//use myVar in remaining code
As i know line starting from symbol # consider as processor command and it will be known and replaced at compile time. But here i have if condition in which validCondition changed run time and according that #define defined.
So in this case how processor will work?
Also any one have batter idea to define different data type variable based on condition?
You could define a wrapper type for these data types:
struct DayAction {
int day;
char *action;
size_t actionlen;
};
Then, have a variable of that type and, depending on your condition, fill in the fields of that variable:
struct DayAction day_action;
if (condition()) {
day_action.day = dt1.day;
day_action.action = dt1.action;
day_acion.actionlen = sizeof dt1.action;
}
After that, you can operate on day_action, since it points into the original data.
If you need to change the dt1.day, make DayAction.day a pointer.
If you don’t need to change the action, make DayAction.action a const char *.
How about keeping only one struct:
typedef struct {
int day;
char *action;
} DataType;
And then based on some condition, invoke malloc() with the proper number of bytes you need:
DataType dt;
if (checkWhateverCondionYouWant)
dt.action = malloc(someSize);
HTH.

Understanding pointer structs in C

I am trying to understand an assignment I have before I have to take a final. I am trying to understand what exactly I am declaring.
So in a given file the typedef struct's are declared as so:
(Struct Declaration)
/** The following two structs must be defined in your <gamename>.c file **/
typedef struct game_position_t *game_position;
/* move struct must code enough information to reverse the move, given the resulting position */
typedef struct move_t *move;
I have then built the structs out as so (yes this has to be separated just because it is interfaced programming):
(Struct Definition)
/** The following two structs must be defined in your <gamename>.c file **/
struct game_position_t {
int mathy;
int numrows;
int *sizes;
};
/* move struct must code enough information to reverse the move, given the resulting position */
struct move_t {
int rownum;
int move_size;
};
Then an example of a functions and declaration of game_position for example is:
(Example Function)
/* return the starting position, NULL if error */
game_position starting_position(int me_first, int argc, char **argv) {
if (argc < 3) {
printf("\n\nToo few arguments, see help below\n\n");
game_help(argv[0]);
return NULL;
}
int mathy;
if (strcmp(argv[2],"search")==0)
mathy = 0;
else if (strcmp(argv[2],"mathy")==0)
mathy = 1;
else {
printf("\n\nSecond argument must be \"search\" or \"mathy\", see help below\n\n");
game_help(argv[0]);
return NULL;
}
int play_default = (argc==3);
if (play_default) printf("\n\nOK, we will play the default game of 7 5 3 1\n\n");
int defaultgame[4] = {7,5,3,1};
game_position result = malloc(sizeof(struct game_position_t)*1);
result->mathy = mathy;
if (result) {
result->numrows = (play_default ? 4 : argc-3);
result->sizes = malloc(sizeof(int)*(result->numrows));
int row;
for (row=0; row<(result->numrows); row++)
(result->sizes)[row] = (play_default ? defaultgame[row] : strlen(argv[row+2]));
}
return result;
}
So my main misunderstanding is when using a struct declaration in this manner, specifically putting the * before the name like this, typedef struct move_t *move;. Is that previous line saying move it a struct pointer or dereferencing move? Continuing from that. When defining them I just use the struct name such as struct move_t. I don't fully understand how they are linking together and in what matter. Then inside the function I just declare game_position, but still need to use a derefencer, 'p->`, to access it fields. So if someone could explain to me when these struct variables are points to structs and when they are the actual struct.
An example of my misunderstanding is that in the Example Function after result was declared. I first thought to use the . operator to access and set it's fields. I then changed it due to compiler errors, but now I want to understand my misunderstanding. And why did I I have to malloc game_position_t and not game_position?
typedef defines a type, so typedef struct move_t *move defines a new type named move, which is a pointer type, pointing to struct move_t. So after this if you define a variable with move ptr, ptr will have a pointer type so that you should use the syntax of accessing members through a pointer. When allocating memory for it, of course you have to specify the exact size of the structure other than the size of a pointer, that's sizeof(struct move_t)

Resources