Okay so I'm having an issue with a current assignment (trust me this is a minuscule part of it) as we are required to write in C code and not C++, and we are not allowed to change certain parts of code. So I have a struct defined:
typedef struct someStruct {
int what;
int something[MAX];
int another[MAX];
} someType;
in main() I initialize all the values in a defined struct:
someType whatever, *whatptr;
EDIT:of course set the pointer to the struct, trying to simplify the code for the example It is present in my code already
whatptr = &whatever;
whatever.what = 0;
// initialize both arrays to hold 0 at all indexes
// Then I must call a function progRun()
progRun(); //I need to pass struct 'whatever' in some way
Now progRun() looks like this:
void progRun(){
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
I can't change anything inside this code except what parameters to pass inside the progRun() function and I can add stuff before printWhat(). I've tried changing progRun to
void progRun(someType *stptr)
then calling it in main as
progRun(whatptr);
but this causes a stack overflow issue for some reason, I've tried stepping through with a debugger and it only occurs when the function is called. Is there a better way to pass the 'whatever' struct to the function so it can be passed into progRun() and printWhat() and can access 'whatever.what'?
Any help would be greatly appreciated! in the meantime I'll try to figure it myself if I can.
EDIT: Something else must be wrong in the code even though everything else has compiled and ran perfectly fine until this code was added. If I can break down the code and find out what's wrong I'll update the question. And no I cannot post the whole code as it is an assignment (this isn't the goal of the assignment trust me it focuses on data forwarding and more, just need to get this basic thing working) Thank you for help everyone.
EDIT: the MAX number used in the struct for something[MAX] and another[MAX] was extremely large ( I left my desktop that I started this project with back home, I'm currently using an old laptop that can't handle large arrays). All the answers below, and some of the stuff I used before now works fine.
void progRun(someStruct *ptr) {
someStruct whatever2 = *ptr;
printWhat(whatever2);
if (whatever2.what == 0) { ...
}
whatptr = &whatever;
progRun(whatptr);
Your problem was that:
you need to pass a pointer to whatever, yet you were passing a variable (whatptr) that had absolutely nothing to do with whatever.
You need to first assign the pointer to whatever into your pointer variable.
You are not dereferencing the pointer in the function
Alternately, get rid of pointer variables:
void progRun(someType *stptr) {
printWhat(*stptr);
if (stptr->what == 0) { ...
}
progRun(&whatever);
Instruction
someType whatever, *whatptr;
is the problem:
*whatptr will not point to the struct whatever unless you do the assignment as follows:
whatptr = &whatever;
Alternatively you could dynamically allocate memory on the heap for a pointer to your struct whatever by using the malloc() function and pass the pointer returned by malloc to the function progrun:
whatptr = (someType*) malloc ( sizeof(someType) );
if (whatptr == NULL) exit (1);
//whatever you need to do with your code
progrun(whatptr); // call function like this
In this case of course you will need to dereference your pointer to access member elements of the struct by using the arrow -> operator:
whatpr->what = 0; // for example
Also, check these tutorials to understand both approaches:
link 1
link 2
If you can't change print and if statements then you should pass your function a copy of your struct:
void progRun( someType whatever ){ // <---Passing by copy
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
and in your main() you should just call the function like this:
someType whatever;
//assign values to members of the struct
progRun(whatever);
and do not need at all to define and assign a pointer to the struct.
Though passing variables to functions by copy (especially when they are objects composed by many variables such as a struct is) is not a good behaviour:
it will require an overhead to copy all member elements
your copy will have a limited scope, which means that any change you do to the variable inside of the function will be lost when your function ends and will not be reflected on variable at main scope
Related
there are various ways to return structure from function like return whole structure or return the pointer only.
returning pointer is useful to avoid stack overhead as we don't needed to return whole structure. In other side for
small structure it is good to go with returning whole structure.
In my case i have below scenario to get structure from another file and thought various methods to use but as i am new to C so still i needed some expert advise like
which method is better? Any issue in it? or any suggestion for new method?
returning large structure as whole cause any stack issue?
file1.c
static struct_type mysruct; //Note : here struct size is 250+ bytes
//Method 1
struct_type getStructDataMethod1()
{
return mysruct;
}
//Method 2
void getStructDataMethod2(struct_type *structPtr)
{
if(structPtr != NULL)
{
memcpy(structPtr, &mysruct, sizeof(struct_type));
}
}
//Method 3
void getStructDataMethod3(struct_type *structPtr)
{
*structPtr = mysruct;
}
file2.c
void myFunction()
{
struct_type mylocalStruct1 = getStructDataMethod1();
struct_type mylocalStruct2;
struct_type mylocalStruct3;
getStructDataMethod2(&mylocalStruct2);
getStructDataMethod3(&mylocalStruct3);
}
The rule of thumb is to always pass structs to function by pointers and never by value, for the reasons you mention yourself. You should only make special case exceptions to this rule in case a struct is very small.
So either method 2 or 3 is the correct way to do it. Apart from the NULL pointer check, they are equivalent.
Minor issue not related to your question: never write functions as void myFunction() in C, this is obsolete style. Use void myFunction(void) instead.
I got the following code:
// file external_module.h
typedef externaldata * externalhdl; // opaque pointer
externalhdl external_Create();
// file internal_module.h
typedef internaldata * internalhdl; // opaque pointer
internalhdl internal_Create();
What i would like to do is to use an opaque pointer of a external module as a opaque pointer inside of my module to save unessasary allocs. Currently my workaround implimentation is:
typedef struct {externalhdl e} internaldata;
internalhdl internal_Create()
{
internalhdl p = (internaldata*) malloc (sizeof(internaldata));
p.e = external_Create();
return p;
}
What I would like to do is use something like:
typedef ??? internaldata; //Don't know how
internalhdl internal_Create()
{
return external_Create();
}
From my point of view it should be possible since both are pointer but I need to get it warning free? Thanks for your help.
The most important thing you need to consider in my opinion, is that you will gain absolutely nothing but darkenss in doing something like this, and that you want to typedef a pointer to another type of pointer. If it is an opaque poitner, it doesn't make sense to typedef it also because you will never access the members of the underlying structure, it might very well be passed as a void * pointer, but when you allocate it, you MUST know it's type because the compiler needs to know it's size and layout in order to allocate it correctly (aligning it correctly for example would be impossible otherwise).
If you don't want to repeatedly use the sizeof operator to allocate the correct size there are two possible approaches1
Use a macro
#define allocate(x) x = malloc(sizeof(*x))
and then
my_type *x;
allocate(x);
but this is horrible and unclear.
Use an allocation function,
my_type *
my_type_alloc()
{
return malloc(sizeof(my_type));
}
such that
my_type *x;
x = my_type_allocate();
this is clean and simple, and you can't do it wrong.
Note that returning the appropriate pointer type just ensures that you will not accidentally do something that might cause undefined behavior, but allocation functions can simply return void * and they will work, that is why I did not cast malloc()'s return value.
Syntax sugar is something that you must be very careful with, because somtimes it looks like you simplified and improved syntax when what you did was hide vital information from the fellow programmer that will read your code, that programmer could even be yourself some time after writing the code.
And your workaround is actually causing one unecessary allocation. In fact, when you finally understand poitners, you will then really avoid unnecessary allocations by not copying data when you will only read from it.
1In both cases, you should check for NULL after the allocation is performed to ensure you can access such pointer without causing undefined behavior
It would seem you are on the right track with the design, it is just the implementation that's questionable. As mentioned in comments, you should never hide pointers behind typedefs and opaque pointers is no exception to this. If the caller believes that these are allocated variables, they may decide to do stupid things like this:
set_obj(obj1, "foo"); // set private data to something
memcpy(&obj2, &obj1); // take a hardcopy of the data (or so we thought)
set_obj(obj1, "bar"); // set private data to something else
print_obj(obj2); // prints "bar", wtf!!!
So stop hiding the pointers.
With some slight modifications you should get the code to work as expected:
external.h
typedef struct external_t external_t;
external_t* external_create (/* parameters here */);
external.c
#include "external.h"
external_t* external_create (/* parameters here */)
{
external_t* ext = malloc(sizeof *ext);
/* initialize stuff here */
return ext;
}
internal.h
#include "external.h"
typedef struct internal_t internal_t;
internal_t* internal_create (/* parameters here */);
internal.c
#include "internal.h"
struct internal_t
{
external_t* ext;
};
internal_t* internal_create (/* parameters here */)
{
internal_t* inter = malloc(sizeof *inter);
inter->ext = external_create (/* parameters here */);
if(inter->ext == NULL)
{
return NULL;
}
/* initialize stuff here */
return inter;
}
The caller will have to use pointers too.
Also, there is no need to cast the result of malloc. Beat the dead horse here:
Do I cast the result of malloc?.
I have two structs in a library I cannot change. p.e:
struct{
uint8_t test;
uint8_t data[8];
}typedef aStruct;
struct{
uint8_t value;
uint8_t unimportant_stuff;
char data[8];
}typedef bStruct;
aStruct a;
bStruct b;
In my application there is a process that permantently refreshs my aStruct's.
Now I have a buffer of bStruct's I want to keep updated as well.
The data[] array is the important field. I don't really care about the other values of the structs.
I already made sure, that on that specific system where the code runs on, a "char" is 8Bits as well.
Now I'd like to make the "b.data" array point to exactly the same values as my "a.data" array. So if the process refreshs my aStruct, the values in my bStruct are up to date as well.
Therefore that in C an array is only a pointer to the first element, I thought something like this must be possible:
b.data = a.data
But unfortunately this gives me the compiler-error:
error: assignment to expression with array type
Is there a way to do what I intend to do?
Thanks in advance
Okay, according to the input I got from you guys, I think it might be the best thing to redesign my application.
So instead of a buffer of bStruct's I might use a buffer of aStruct*. This makes sure my buffer is always up to date. And then if I need to do something with an element of the buffer, I will write a short getter-function which copies the data from that aStruct* into a temporary bStruct and returns it.
Thanks for your responses and comments.
If you want b.data[] array to point to exactly the same values, then you can make data of b a char* and make it point to a's data.
Something like
struct{
uint8_t value;
uint8_t unimportant_stuff;
char* data;
}typedef bStruct;
and
b.data = a.data;
But, keep in mind, this means that b.data is pointing at the same memory location as a.data and hence, changing values of b.data would change values of a.data also.
There is another way of doing this. It is by copying all the values of a.data into b.data. Then, b.data would merely contain the same values as a.data, but it would point to different memory locations.
This can either be done by copying one by one. In a for loop for all the 8 elements.
Or, to use memcpy()
NOTE
Arrays cannot be made to point to another memory locations. As they are non modifiable l-value. If you cannot modify the structs, then you have to use the second method.
What you are asking is not possible when you can not modify the existing struct definitions. But you can still automate the functionality with a bit of OO style programming on your side. All of the following assumes that the data fields in the structs are of same length and contain elements of same size, as in your example.
Basically, you wrap the existing structs with your own container. You can put this in a header file:
/* Forward declaration of the wrapper type */
typedef struct s_wrapperStruct wrapperStruct;
/* Function pointer type for an updater function */
typedef void (*STRUCT_UPDATE_FPTR)(wrapperStruct* w, aStruct* src);
/* Definition of the wrapper type */
struct s_wrapperStruct
{
STRUCT_UPDATE_FPTR update;
aStruct* ap;
bStruct* bp;
};
Then you can can create a factory style module that you use to create your synced struct pairs and avoid exposing your synchronization logic to uninterested parties. Implement a couple of simple functions.
/* The updater function */
static void updateStructs(wrapperStruct* w, aStruct* src)
{
if ( (w != NULL) && (src != NULL) )
{
/* Copy the source data to your aStruct (or just the data field) */
memcpy(w->ap, src, sizeof(aStruct));
/* Sync a's data field to b */
sync(w); /* Keep this as a separate function so you can make it optional */
}
}
/* Sync the data fields of the two separate structs */
static void sync(wrapperStruct* w)
{
if (w != NULL)
{
memcpy(w->bp->data, w->ap->data, sizeof(w->bp->data));
}
}
Then in your factory function you can create the wrapped pairs.
/* Create a wrapper */
wrapperStruct syncedPair = { &updateStructs, &someA, &someB };
You can then pass the pair where you need it, e.g. the process that is updating your aStruct, and use it like this:
/* Pass new data to the synced pair */
syncedPair.update( &syncedPair, &newDataSource );
Because C is not designed as an OO language, it does not have a this pointer and you need to pass around the explicit wrapper pointer. Essentially this is what happens behind the scenes in C++ where the compiler saves you the extra trouble.
If you need to sync a single aStruct to multiple bStructs, it should be quite simple to change the bp pointer to a pointer-to-array and modify the rest accordingly.
This might look like an overly complicated solution, but when you implement the logic once, it will likely save you from some manual labor in maintenance.
I have created an abstract data type in C that is based off a structure. Inside this structure, there are pointers to other ADTs that are also based off of structures. I want to know how/if I can properly initialize the pointers on the inside and get rid of my memory access violation errors. The code is below:
typedef struct insideADT1_S{
int someConstant1;
int someArrray1[500];
} insideADT1_T
typedef struct insideADT2_S{
int someConstant2;
int someArray2[500];
} insideADT2_T
typedef struct outsideADT_S{
insideADT1_T *insidePTR1;
insideADT2_T *insidePTR2;
} outsideADT_T
I create the outside structure and pass it to a function. Inside the function, I try to get one of the inside members, and I crash and get a memory access error. An example is below:
outsideADT_T *outsidePTR;
SomeFunction(&outsidePTR);
The inside of SomeFunction looks like:
void SomeFunction(outsideADT_T *outsidePTR){
//===Fill Array of Inside ADT===//
for (i=0; i<500; i++){
outsidePTR->insidePTR1->someArray1[i] = i; //OOPS! Memory Access Violation! FAIL!
}
}
However, accessing like this gives me memory access violations. Note that I can solve the problem by using the structure versions, instead of the ADTs, and not defining pointers to those structures. For instance:
typedef struct outsideADT_S{
struct insideADT1_S insideSTC1;
struct insideADT2_S insideSTC2;
} outsideADT_T
void SomeFunction(outsideADT_T *outsidePTR){
//===Fill Array of Inside ADT===//
for (i=0; i<500; i++){
outsidePTR->insideSTC1.someArray1[i] = i;
}
}
Works fine. Why does the first method fail when the second one doesn't? What am I doing wrong the first time, and how can I fix it?
You call SomeFunction with a pointer to a pointer to an outsideADT_T structure (double reference), whereas SomeFunction is declare to just take a pointer to that structure (single reference). Try this:
outsideADT_T outsidePTR; // <-- notice the lack of '*'
SomeFunction(&outsidePTR);
Furthermore, you dereference insidePTR1 without initializing it. You'll need to allocate some memory for it at the beginning of SomeFunction:
outsidePTR->insidePTR1 = malloc(sizeof(insideADT1_T));
Same goes for insidePTR2.
I have a quite complicated code in that is working fine on AIX but core dumping in Solaris. I tried to make it as simplified as possible.
Below is a global structrue having a pointer to a function
custom_struct_1 my_struct1 = {
intValue1, intValue2, intValue3, func3
};
This is a second structure having a pointer to the first one as a field
custom_struct_2 my_struct2 = {
intValue1, intValue2, &my_struct1
};
below is the flow
func1(){
custom_struct *my_dumping_struct;
memset(my_struct, 0, sizeof(my_struct);
func2(my_dumping_struct, &my_struct2);
}
func2(custom_struct *my_dumping_struct, custom_struct_2 *my_struct2 ){
custom_struct1 *my_cust1;
// Some conditions go here
my_cust1 = &my_struct2->custom_struct_1;
my_cust1->struct_func(my_dumping_struct);
}
func3(custom_struct *my_dumping_struct)
{
// Here when trying to access any field of the passed structure
// a core dump is occuring
if(my_dumping_struct->intValue1 == 0)
{
....
}
}
I appreciate any help. It is driving me crazy. I tried multipile things like defining the dumping structure without a pointer at first, using
memset(&my_dumping_structre, 0, sizeof(my_dumping_struct))
and passing it with a reference to the other functions it still core dumps.
EDIT
Definition of the structures are as below:
struct custom_struct {
int intValue1;
int intValue2;
};
struct custom_struct_1 {
int intValue1;
int intValue2;
int intValue3;
int (*struct_func)(custom_struct *my_struct);
};
struct custom_struct_2 {
int intValue1;
int intValue2;
struct custom_struct_1 *my_struct;
};
Thanks
The expression &my_struct2->custom_struct_1 doesn't do what you expect it to do. It returns the address of the pointer, in other words a pointer to a pointer to the custom_struct_1 structure.
Don't use the address-of operator & and it should work much better.
You have this problem in more places, actually almost everywhere you use a pointer you take the address of the pointer instead.
You might also have another problem, unless you don't show us the complete code of func1, and that is that you don't initialize the my_dumping_struct pointer before using it. That means it will point to a seemingly random address, and all dereferencing of that pointer will be undefined behavior and most likely a crash.
Actually, you should have lots of compiler warnings screaming at you about all of this.
malloc seemed to solve the problem
custom_struct *my_dumping_struct = malloc(sizeof *my_dumping_struct);
Sorry if wasn't very clear and thanks all for your suggestions and help