FINAL EDIT: First of all, thank you guys for your patience. In the future I'll try to bring an MCVE to any questions I ask.
The program seems to be working fine now - I may have unwittingly deleted a typo or something.
This question annoys me quite a bit - I didn't choose to implement it this way, but it's required and I need to resolve it.
I've got a function that's supposed to read a piece of data from a struct, like this:
typedef struct {
int data;
char extraneous_stuff[];
} MyStruct;
...
//there's also a ParentStruct that holds a MyStruct array
...
void read_data(ParentStruct *parent, int which_MyStruct, int *data) {...
What I need to do is use the int *data as an out-parameter to copy the int data from inside a selected MyStruct. The problem I'm having, of course, is that both the out-parameter and the MyStruct field have exactly the same name. I found that trying to copy directly, i.e. *data = parent->array[which_MyStruct].data; compiled, but the data didn't actually get copied to the out parameter.
In order to hold to specifications I'm not supposed to change the names of the parameters here. Am I doomed?
EDIT: I included the following print statements inside the function:
printf("%d", *data);
printf("%d", parent->array[which_MyStruct].data);
and, having put
int n = 0;
void read_data(*parent, which_MyStruct, &n)
I got back
0
0
as a result.
EDIT 2:
OK, this is very weird. I have this:
MyStruct current = parent->array[which_MyStruct];
printf("%s", current.extraneous_stuff[0]);
printf("%d", *data);
printf("%d", parent->array[which_MyStruct].data);
and now suddenly "parent->array[which_MyStruct].data" has the appropriate value.
Maybe this is undefined behavior, because the only change I made was to include the print statement "printf("%s", current.extraneous_stuff[0]);" and the output changed.
Related
Given I'll return a large struct in a function like here:
#include <stdio.h>
// this is a large struct
struct my_struct {
int x[64];
int y[64];
int z[64];
};
struct my_struct get_my_struct_from_file(const char *filename) {
int tmp1, tmp2; // some tmp. variables
struct my_struct u;
// ... load values from filename ...
return u;
}
int main() {
struct my_struct res = get_my_struct_from_file("tmp.txt"); // <-- here
printf("x[0] = %d\n", res.x[0]);
// ... print all values ...
}
At the place marked by here, do I have to assume that this large struct is copied or is it likely that the compiler does something to avoid this?
Thank you
… do I have to assume that this large struct is copied…
No, of course you do not have to make that assumption. Nobody requires you to make that assumption, and it would be unwise to adopt the statement as an assumption rather than deriving it from known information, such as compiler documentation or inspection of the generated assembly code.
In the specific code you show, it is likely good compilers will optimize so that the structure is not copied. (Testing with Apple Clang 11 confirms it does this optimization.) But that is likely overly simplified code. If a call to get_my_struct_from_file appears in a translation unit separate from its definition, the compiler will not know what get_my_struct_from_file is accessing. If the destination object, res in this example, has had its address previously passed to some other routine in some other translation unit, then the compiler cannot know that other routine did not stash the address somewhere and that get_my_struct_from_file is not using it. So the compiler would have to treat the structure returned by get_my_struct_from_file and the structure the return value is being assigned to as separate; it could not coalesce them to avoid the copy.
To ensure the compiler does what you want, simply tell it what you want it to do. Write the code so that the function puts the results directly in the structure you want to put it in:
void get_my_struct_from_file(struct my_struct *result, const char *filename)
{
…
}
...
get_my_struct_from_file(&res, "tmp.txt");
At the place marked by here, do I have to assume that this large struct is copied or is it likely that the compiler does something to avoid this?
Semantically, the structure is copied from the function's local variable to the caller's variable. These are distinct objects, and just like objects of other types, setting one structure equal to another requires copying from the representation of one to the representation of the other.
The only way to avoid a copy would be for the compiler to treat the local variable as an alias for the caller's structure, but that would be wrong in the general case. Such aliasing can easily produce observably different behavior than would occur without.
It is possible that in some specific cases, the compiler can indeed avoid the copy, but if you want to ensure that no copying happens then you should set up the wanted aliasing explicitly:
void get_my_struct_from_file(const char *filename, struct my_struct *u) {
int tmp1, tmp2; // some tmp. variables
// ... load values from filename into *u
}
int main() {
struct my_struct res = { 0 };
get_my_struct_from_file("tmp.txt", &res);
printf("x[0] = %d\n", res.x[0]);
// ... print all values ...
}
In a homework task I must gain access to object specifics (i.e pID, Code), which are located in a structure. However, I need to link my function with the objects first (**ppObjects), but since I am dealing with a doublepointer, I seem to be having an issue.
It is worth noting that when I tried the same commands but function was PrintNewObject(HeaderC* pStruct4) it worked fine - so I am guessing it is an issue with me having to use doublepointer when dealing with pStruct4.
I have provided the code that I have tried below. While compiling it shows no error, but upon trying to print something from it, it says that obj is a nullpointer.
The function that I would like to link with ppObjects.
int InsertNewObject(HeaderC** pStruct4){
HeaderC* testinH;
for (testinH = *pStruct4; testinH != NULL; testinH = testinH->pNext)
{
int count = 0;
while (count < 26) //one for every letter in the alphabet, as ppObjects is an array
{
Object9* obj;
obj = (Object9*)testinH->ppObjects[count]; //the line that does not seem to properly define
printf("%lu", obj->Code); //running this line crashes my program
count++;
}
}
Header, where we can see that ppObjects is a doublepointer.
typedef struct headc
{
void **ppObjects; // Pointer to the array of pointers to objects.
// Objects may be of types Object1-10
char cBegin; // The first letter of ID of objects related to
// header is cBegin.
struct headc *pNext;
} HeaderC;
The object I was provided in the hometask is below. This is what I would get access to after defining
typedef struct ob9
{
char *pID;
unsigned long int Code;
Date3 *pDate3;
struct ob9 *pNext;
} Object9;
I get an error saying that obj is nullpointer when I try to print anything from obj.
If this is poorly worded, I am sorry. I tried my best to make this understandable yet not too long. Any help is appreciated!
Hi i have following situation
typedef struct
{
int a;
Name team[5];
Sport sport[5];
} School;
where Name and Sport are also structs,
typedef struct
{
char arry[20];
}Name;
typedef struct
{
char arry[20];
int tag;
}Sport;
then
School first_school, second_school;
I populate them individually, then at some point I do
first_school = second_school
But I step through code this line doesn't seem to work. How should I copy ?
But I step through code this line doesn't seem to work. How should I copy ?
It's entirely correct to copy struct like that
first_school = second_school; // valid
If it doesn't work as expected then the error is somewhere else. For example, you need to do strcpy() for string members.
Structures are values that can be assigned. They can contain arrays, which by themselves are not assignable, but being inside a struct makes it possible.
That code is fine, except you need to reverse the order of the declarations, since School references Name and Sport they must be declared first.
I tested it and it works just fine after reversing the declaration order, this prints hello:
int main(void) {
School foo, bar;
strcpy(bar.team[0].arry, "hello");
foo = bar;
printf("'%s'\n", foo.team[0].arry);
return 0;
}
There is probably something else wrong with your initialization of the second_shool, or you're failing to verify that it worked.
It will work for most members, but you have one that cannot be copied like that arry. You should copy one element at a time from the target to the destination instances.
Note that there are functions that take care of such copying like memcpy(). But you cannot copy an array by assignment like you do with an int or a struct actually.
I'm tasked with adding the quick-fit allocation algorithm to MINIX, and as such need to use structures a lot. However, I came accross something for which I cannot find any resources on a solution.
The below code is a quick example I made to demonstrate the issue I have met with.
#include <stdlib.h>
#include <stdio.h>
struct some_struct {
int h_count;
};
void why();
struct some_struct * myStruct;
int main(){
myStruct = (struct some_struct *) malloc(sizeof(struct some_struct));
myStruct->h_count=0;
printf("%d\n", myStruct->h_count);
why(&myStruct);
return 0;
}
void why(struct some_struct * t_some_struct){
printf("%d\n", t_some_struct->h_count);
}
The output of the printf in the function why is different from the output given in main. The value printed by why is a seemingly random number that changes every time the program is ran.
Output:
0
7870280
Press any key to continue . . .`
The 7870280 changes on every run. I would assume it is printing some kind of memory value or something, but that's just a guess as I have no idea really.
As such, I thought I'd ask here for the benefit of others alongside myself:
Why does this occur?
Is my syntax the issue here?
How do I use a pointer to a structure as a parameter for some function, then reference the given structure's members in the scope of the function? (I'd like to use h_count for t_some_struct as 0)
Thanks
The function why expects a pointer whereas you are passing a pointer to pointer. Call as
why(myStruct); (by the way, myStruct is a global variable, so passing is a bit superfluous here). Rest of your accessing the struct member is fine.
Not directly related but some general suggestions:
1) Use standard prototype for main() such as int main(int argc, char*argv[])
2) Casting the result of malloc is needless and error-prone.
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