Checked couple of stack overflow questions/answers but none correspond to what I am trying to do. Here is it:
I have a c object file myobject.c containing struct type populated at run time (as initialised by main file having the main() function. Below is the skeletal structure of myobject.c:
typedef struct
{
uint16_t ID;
float tempo;
char unit[10];
unsigned long timestamp;
} prv_data_t;
static uint8_t prv_value(lwm2m_data_t* dataP,
prv_data_t* tempData)
{
uint8_t ret = COAP_205_CONTENT;
//TO DO here
.
.
.
return ret;
}
static uint8_t prv_read(..paramList)
{
//TO DO here
.
.
//then call prv_value here
result = prv_value((*tlvArrayP)+i, tempData);
return result;
}
object_t * get_object(){
//this func get called by main.c to initialize myobject
}
Skeletal structure of the main.cfile:
myFunc(mypar p) {
}
main(){
//initialize myobject
//.....
//access myobject struct member here, pass to myFunc call
myFunc(tempo)
}
The main.c initialises myobject.c. Now I want to access tempo a member of prv_data_tfrom myobject.cfor some computation. How do I achieve such a task without exposing prv_data_t in main.c?
EDIT: here's what I mean by main.c initialises myobject.c and all other objects, please:
/*
* Now the main function fill an array with each object,
* Those functions are located in their respective object file.
*/
objArray[0] = get_security_object();
if (NULL == objArray[0])
{
fprintf(stderr, "Failed to create security object\r\n");
return -1;
}
.
.
.
The main file actually contains the main()function.
You can avoid exposing your private data by doing:
Let main work with pointers to incomplete type struct prv_data_t
Implement getter-functions (and setter-functions) for members that you allow main to access
Something like this:
a.h
#include <stdio.h>
struct prv_data_t; // Incomplete type
struct prv_data_t * get_obj();
float get_tempo(struct prv_data_t * this);
a.c
#include <stdio.h>
#include <stdlib.h>
struct prv_data_t
{
int ID;
float tempo;
char unit[10];
unsigned long timestamp;
};
float get_tempo(struct prv_data_t * this)
{
return this->tempo;
}
struct prv_data_t * get_obj()
{
struct prv_data_t * p = malloc(sizeof *p);
p->tempo = 42.0;
return p;
}
main.c
#include <stdio.h>
#include "a.h"
int main()
{
struct prv_data_t * p = get_obj();
printf("%f\n", get_tempo(p));
// The line below can't compile because the type is incomplete
// printf("%f\n", p->tempo);
return 0;
}
So with this kind of code main only knows that there exists a struct prv_data_t but main knows nothing about the members of that struct.
Related
How can I send a pointer that´s in another module to a new module?
Hello, I´m just starting a Programming Proyect in c of a game for class. This game contains a struct called game that also contains differents types data like Players ir Objects. Those structs are identified by a long Id, classified so that the objects have an Id between #0 and #100 for example.
To make it easier I´ve been creating a function "what_id" that recibing just an Id it returns a pointer to the struct that corresponds to it. I know how by sending the 'game' struct where are contained all the ids, and an Id, return the variable, but there´re modules that do not use in any case that big 'game' variable, for example player.c.
How can I send 'game' to this function without having it?
typedef struct _Game{
Player* player[MAX_PLAYERS + 1];
Object* object[MAX_OBJECTS + 1];
Space* spaces[MAX_SPACES + 1];
T_Command last_cmd;
} Game;
typedef struct _Object{
Id id;
char name[MAX_SPACES];
}
void* what_id(Game* game, Id id){
if(id == NO_ID) return ERROR;
if(0 <id<=MAX_SPACES){
return what_space(game->space, id);
}else if(MAX_SPACES<id<=(MAX_OBJECTS+MAX_SPACES)){
return what_object(game->object, id);
}else if((MAX_OBJECTS+MAX_SPACES<id<(MAX_PLAYERS+MAX_OBJECTS+MAX_SPACES)){
return what_player(game->player, id);
}else {
fprinf(stderr,"Id asigment max stacked.";
return ERROR;
}
}
Space* what_space(const Space* space, Id id){
int i;
for(i=0;i<MAX_SPACES;i++){
if(space[i]->id == id)return space[i];
}
fprintf(stderr, "Error no space_id %d founded", id);
return ERROR;
}
It's not clear what you mean by "module", or where Game is going to come from. If by modules you mean separate sources files that produce separate object files, there are generally two ways to do this.
The first is to declare a global variable and import it as an extern:
file1.c:
// declare struct
typedef struct {
int value;
} Foo;
// declare global variable
Foo *globalfoo;
// declare external function from another module
void printfoo();
void main()
{
Foo foo;
foo.value = 3;
globalfoo = &foo;
printfoo();
}
file2.c:
#include <stdio.h>
// declare struct
typedef struct {
int value;
} Foo;
// declare variable from another module
extern Foo *globalfoo;
void printfoo()
{
printf("foo: %d\n", globalfoo->value);
}
The other way to do it is to pass it via a function argument:
file1.c:
typedef struct {
int value;
} Foo;
void printfoo(Foo *foo);
void main()
{
Foo foo;
foo.value = 3;
printfoo(&foo);
}
file2.c:
#include <stdio.h>
typedef struct {
int value;
} Foo;
void printfoo(Foo *foo)
{
printf("foo: %d\n", foo->value);
}
You can avoid re-declaring structs and functions in multiple source files by putting them in a header file and #including it:
myproject.h:
typedef struct {
int value;
} Foo;
void printfoo(Foo *foo);
file1.c:
#include <myproject.h>
void main()
{
Foo foo;
foo.value = 3;
printfoo(&foo);
}
file2.c:
#include <myproject.h>
#include <stdio.h>
void printfoo(Foo *foo)
{
printf("foo: %d\n", foo->value);
}
I have a struct that I want to statically allocate at compile time but I'm not sure how to return a pointer to the inner structure.
typedef struct
{
int d;
} innerStruct;
typedef struct
{
int a;
int b;
int c;
innerStruct inner;
} myStruct;
static myStruct m1;
innerStruct * getMyStructPtr()
{
myStruct * ptr = &m1;
return ptr->inner;
}
int main()
{
innerStruct * retval = getMyStructPtr();
return 0;
}
Link to online compiler: https://onlinegdb.com/SJAFJCy0Z
Check the data types!!
Your function promised to return a innerStruct *, whereas your code attempts to returns a innerStruct. They are neither same nor compatible. Fix either and use it appropriately.
Following the function call, it appears that you may want to write
return &(ptr->inner); // return type innerStruct *
I give the following example to illustrate my question:
1) a.h where the structure is declared
a.h
struct A_Structure;
typedef struct A_Structure *A_Structure_Ptr;
2) b.c where the structure definition is implemented
#include "a.h"
struct A_Structure
{
int a;
int b;
int c;
};
2) main.c where the structure is invoked
#include <stdlib.h>
#include "a.h"
int main ()
{
struct A_Structure b;
return 0;
}
However, I cannot compile these C codes as I receive the following error message:
>main.c(6): error C2079: 'b' uses undefined struct 'A_Structure'
Any ideas? Thank in advance.
EDIT:
#include <stdlib.h>
#include "a.h"
int main ()
{
struct A_Structure *b=0;
b=(struct A_Structure*)malloc(12);
b->a=3;
free(b);
return 0;
}
I tried to create the structure in this way but still failed.
You probably need this:
struct A_Structure
{
int a;
int b;
int c;
};
in a.h
This is the typical approach when defining structs
If you're trying to implement an opaque pointer, you need a function that instantiates A_Structure and returns a pointer, as well as functions that manipulate A_Structure pointers:
in a.h
A_Structure_Ptr CreateA(int a, int b, int c);
void FreeA(A_Structure_Ptr obj);
void SetA_a( A_Structure_Ptr obj, int a );
int GetA_a( A_Structure_Ptr obj );
// etc.
in b.c
A_Structure_Ptr CreateA(int a, int b, int c)
{
A_Structure_Ptr s = malloc( sizeof(A_Structure) );
s->a = a;
s->b = b;
s->c = c;
}
void FreeA(A_Structure_Ptr obj)
{
free( obj );
}
void SetA_a( A_Structure_Ptr obj, int a )
{
obj->a = a;
}
in main.c
int main ()
{
struct A_Structure *b = CreateA( 1, 2, 3);
SetA_a( b, 3 );
FreeA(b);
return 0;
}
When you put the structure declaration in a header file, but leave the definition in the .c file, this is known as using an opaque pointer API.
In an API like this, consumers only use pointers to the objects. Only the implementation needs to know the size or contents of the object. This is how you do OOP in C, and is key to information hiding which provides better decoupling of components. Here's a more complete example:
foo.h
struct foo; // forward declaration
struct foo *foo_create(void);
void foo_use(struct foo *f);
void foo_destroy(struct foo *f);
foo.c
#include <stdlib.h>
#include "foo.h"
struct foo {
int a, b, c; // Consumers don't know about these!
};
struct foo *foo_create(void)
{
struct foo *f = malloc(sizeof(*f));
if (!f)
return NULL;
*f = (struct foo) {
.a = 1,
.b = 2,
.c = 3,
};
return f;
}
void foo_use(struct foo *f)
{
// something with f->a, f->b
}
void foo_destroy(struct foo *f)
{
free(f);
}
main.c
#include "foo.h"
int main(void)
{
struct foo *f; // As a consumer of foo, we can only use **pointers**
f = foo_create();
if (!f)
return 1;
// I cannot access the members of `struct foo` here.
// In an opaque API, the struct members are considered
// an implementation detail and cannot be used outside
// of the implementation.
foo_use(f);
foo_destroy(f);
return 0;
}
You have to decide whether you want to hide the details of the structure from the "outside" or not. If you don't want to hide them, just put the structure definition in a.h. Hiding it ensures better decoupling and central control of your b.c over the content, but that means you have to provide a way to create an object in b.c (e.G.
struct A_Structure *create_A_Structure(void);
and use this from the outside.
an unrelated stylistic advice: better don't typedef pointers. While your _Ptr suffix makes it kind of obvious, it's still better to just have the asterisk everywhere because that is what C programmers are used to, so the fact that it's a pointer is obvious at the first glance.
I'd suggest something like this:
/* header */
typedef struct A A;
A *A_create(void);
/* implementation */
struct A
{
int foo;
}
A *A_create(void)
{
return malloc(sizeof(A));
}
To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...
I am trying to change my C functions of nested structures to operate on pointers instead of passing and making copies of the structures which are quite large in reality.
here is a simplified version of what I want to do passing the structures around....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
outer1 = get_outer ();
}
struct OuterStruct get_outer (void)
{
struct OuterStruct thisOuter;
thisOuter.inner1 = get_inner (void);
thisOuter.outerResult = get_result (thisOuter.inner1);
return thisOuter;
}
struct InnerStruct get_inner (void)
{
struct InnerStruct thisInnner;
thisInner.int1 = 1;
thisInner.int2 = 2;
return thisInner;
}
int get_result (struct InnerStruct thisInner)
{
int thisResult;
thisResult = thisInner.int1 + thisInner.int2;
return thisResult;
}
but the structure is quite large in reality and this is a frequent operation, so I'd rather pass around the pointers. Just not sure how the syntax works for nested structures like this. Here is my attempt....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
get_outer (&outer1);
}
void get_outer (struct OuterStruct *thisOuter)
{
get_inner (&(thisOuter->inner1));
thisOuter->outerResult = get_result (&(thisOuter->inner1));
}
void get_inner (struct InnerStruct *thisInner)
{
thisInner->int1 = 1;
thisInner->int2 = 2;
}
int get_result (struct OuterStruct *thisInner)
{
int thisResult;
thisResult = thisInner->int1 + thisInner->int2;
return thisResult;
}
You should really look up more about how pointers work. But here is some sample C++ code. Notice the "&" tells your compiler to "not send the struct itself" to the function but a pointer to it. Just a warning never return a reference to a variable (unless you know what you are doing).
#include <iostream>
struct MyStruct
{
int a;
int b;
};
using namespace std;
void printStruct(MyStruct * mypointer) {
cout << "MyStruct.a=" << mypointer->a << endl;
cout << "MyStruct.b=" << mypointer->b << endl;
}
int main()
{
MyStruct s;
s.a = 2;
s.b = 1;
printStruct(&s);
return 0;
}
This will illustrate an easy way to pass pointers to structs. It is a much more efficient way to pass data around, especially when, as you say, the data can get very large. This illustration uses a compound struct, (struct within struct) with an array and pointer declared to pass around. Comments in code explain things.
This will all build and run so you can experiment with it. i.e., follow the data along with execution.
Here is an easy way: (using my own structs)
typedef struct {
int alfha;
int beta;
} FIRST;
typedef struct {
char str1[10];
char str2[10];
FIRST first;
}SECOND; //creates a compound struct (struct within a struct, similar to your example)
SECOND second[5], *pSecond;//create an array of SECOND, and a SECOND *
SECOND * func(SECOND *a); //simple func() defined to illustrate struct pointer arguments and returns
int main(void)
{
pSecond = &second[0]; //initialize pSecond to point to first position of second[] (having fun now)
SECOND s[10], *pS; //local copy of SECOND to receive results from func
pS = &s[0];//just like above;
//At this point, you can pass pSecond as a pointer to struct (SECOND *)
strcpy(pSecond[0].str2, "hello");
pS = func(pSecond);
// printf("...", pS[0]...);//pseudo code - print contents of pS, which now contains any work done in func
return 0;
}
SECOND * func(SECOND *a) //inputs and outputs SECOND * (for illustration, i.e., the argument contains all
{ //information itself, not really necessary to return it also)
strcpy(a[0].str1, "a string");
return a;
}
Although there is not much going on in func(), when the pointer returns to main(), it contains both the value copied in main, and the value copied in fucn(), as shown here:
Results: (in code)
Contents in pSecond: