struct copy in c where struct are elements - c

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.

Related

C macro to get member of struct

Consider the following program:
#include <stdio.h>
typedef struct structType {
int someVal;
int otherVal;
// ...more members used for other purposes
} structType;
void myFunc(structType * theStruct, int theVal) {
// Do something
}
int main()
{
structType myStruct;
myStruct.someVal = 5;
myStruct.otherVal = 10;
myFunc(&myStruct, myStruct.someVal);
myFunc(&myStruct, myStruct.otherVal);
return 0;
}
When calling myFunc() I need to pass both a pointer to the struct itself, and one of the values contained withing the struct.
Can I somehow make a macro so that myFunc() could be called something like:
MY_FUNC_MACRO(myStruct, someVal);
MY_FUNC_MACRO(myStruct, otherVal);
So that the struct pointer only needs to be typed once, and then the name of the member variable without passing the struct name once again.
I know about the stringilize macros like # an ##, but afaik that only goes from literal name to string. I need to go the other way, to somehow concatenate multiple strings into one literal name.
You don't need anything fancy
#define MY_FUNC_MACRO(A,B) (myFunc(&(A), (A).B))
works.
It's a little bit fragile though because B could be anything.
If you've got more nested structs and the middle layer is known at compile time, you can do this:
#define MY_FUNC_MACRO(A,B) (myFunc(&(A), (A).memberStruct.B))
I think you can simply use typedef like:
typedef structTypePointer *structType;
and the caller to function turn into:
myFunc(structTypePointer, myStruct.someVal);
or
myFunc(structTypePointer, structTypePointer->someVal);

Using a struct inside a struct

How can I use struct A to modify the data inside a struct B. Which has no name, just a type.
struct A {
struct B;
};
struct B {
int data;
};
Since this is for school, I can't change the code above. I can only use it. I tried something like this for my main but it doesn't work
int main (){
struct A myStruct;
myStruct.B.data = 3;
return 0;
}
Thanks in advance.
Edit: Sorry I was just trying to post this as fast as possible that's why I didn't post this with proper c syntax. Anyway, it's my fault for not being clear enough on my question.
I'm aware that my main doesn't work I just want to know if it's ever possible to access the data inside struct B without declaring a name for it inside struct A as I have above. This is the code I was given by a teacher, so I didn't want to modify the structs because I thought maybe she wants us to brainstorm a way to use it the way she wrote it.
The way iharob explains it works perfectly by declaring struct B before struct A, and actually giving a name to struct B.
Is it simply not possible to access that data inside struct B without giving it a name?
The code you posted is not even c code, it would not compile.
Your main mistake is that you don't need to use the struct name to access the member. This should be good
struct B
{
int data;
};
struct A
{
struct B member;
};
int main(void)
{
struct A instance;
instance.member.data = 3;
return 0;
}
I assume that you posted some sample code, don't do that. Post the actual code that has issues. The code you posted is completely invalid because some one of the definitions lack the type, you can't declare structs without using struct in c except if you typedef it. So please post the actual code the next time.
And don't build such complicated structs with struct members unless you really know what you are doing.

Transferring struct of mixed types to same struct in different memory location

I'm trying to make a small routine that will allow me to make two copies of a struct via pointers and transferring data from one struct to the other only if the other struct contains no data at that point. I am successful with copying the first string over (struct member a) and the second struct member is ok, but the third and fourth are incorrect.
#include "stdio.h"
#include "string.h"
struct A{
char a[4];
long b;
unsigned long c;
char d;
};
int main(){
char mb[600];
struct A *m1=(struct A*)mb;
char *p=(char*)m1;
struct A *m2=(struct A*)(mb+100);
char *pp=(char*)m2;
memcpy(m1->a,"123",4);
m1->b=-123;
m1->c=123;
m1->d='X';
m2->b=-456;
unsigned long q=sizeof(m2);
while (q-- > 0){
if (*pp=='\0'){*pp=*p;}
pp++;p++;
}
printf("A=%s B=%ld C=%ld D=%c\n",m2->a,m2->b,m2->c,m2->d);
}
Compilation of the code works fine. When I do run it, I see these results:
A=123 B=-456 C=0 D=
What I'm expecting instead is:
A=123 B=-456 C=123 D=X
I don't want to rewrite the code so that I individually check the value of each member for data. The struct I will work with will be much larger later on and checking each member using strcmp or direct comparison will take up alot of lines of code. I'm looking for something more compact.
What can I do to fix this?
UPDATE:
I changed my code and now tried using this while loop instead of the one above:
while (q-- > 0){
if (pp[q]=='\0'){pp[q]=p[q];}
}
and the results are still the same (not what I want).
First off, you’re relying on mb being initialized to all zeros, which seems to have happened incidentally when you ran it, but is not guaranteed. If you want it to be initialized to all zeros (and it looks like you do), do that explicitly:
memset(mb, 0, sizeof(mb));
That said, your problem is that you’re only copying sizeof(m2) bytes. m2 is a pointer, so sizeof(m2) is the size of a pointer, not the size of struct A. You probably want sizeof(*m2) instead.

using pointer to an array

currently, I'm facing a problem with my code and my understanding of pointer. here's the code
struct command
{
int type;
int *input;
int *output;
union{
struct command *command[2];
char **word;
}u;
};
to my understanding, the instance struct command *command[2] is an array of pointer to array of command. So I allocate the array with these:
cur_command->u.command[0] = malloc(sizeof(struct command[2]));
So it give me a 2d array of command. However my teacher told me that struct command *command[2] is a pointer to an array command size 2. So cur_command->u.command[0] give the first command element instead of a pointer to a command array size two. My question is, how can I allocate the memory to develop this kind of behavior. thx
First off, I would suggest changing the name of the one variable to, e.g. cmd instead of command to reduce confusion. That is:
....
union{
struct command *cmd[2];
char **word;
}u;
....
Now, as a couple other comments have pointed out, cur_command->u.cmd is an array of two pointers to struct command. cur_command->u.cmd[0] is the first of the two pointers, and cur_command->u.cmd[1] is the second. In order to use either of them, they should be initialized to be pointers to actual struct command objects:
cur_command->u.cmd[0] = malloc(sizeof(struct command));
cur_command->u.cmd[1] = malloc(sizeof(struct command));
Then, you can use either one in the same way you use your cur_command, which is also a pointer to struct command. That is, you can set some of the fields:
cur_command->u.cmd[0]->type = 1;
....
Don't forget to free memory when you're done with it:
free(cur_command->u.cmd[0]);
free(cur_command->u.cmd[1]);
Since the structure is recursive, you may need some recursive code to correctly free all the memory, depending on how deeply you chain these things together...
Also note, that in your posted code (malloc(sizeof(struct command[2]))), the sizeof(...) bit isn't doing what you think it is. I'm not entirely sure it should even compile, as you can't treat a struct as an array like that...

What does the code below mean, in regards to structs in C?

I'm really new to C programming and I'm still trying to understand the concept of using pointers and using typedef structs.
I have this code snippet below that I need to use in a program:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
I'm not exactly sure what this does - to me it seems similar as using interfaces in Objective-C, but I don't think that's the case.
And then I have this line
pStudentRecord* g_ppRecords;
I basically need to add several pStudentRecord to g_ppRecords based on a number. I understand how to create and allocate memory for an object of type pStudentRecord, but I'm not sure how to actually add multiple objects to g_ppRecords.
defines a pointer to the struct described within the curly bracers, here is a simpler example
typedef struct {
int x;
int y;
}Point,* pPoint;
int main(void) {
Point point = {4,5};
pPoint point_ptr = &point;
printf("%d - %d\n",point.x,point_ptr->x);
pPoint second_point_ptr = malloc(sizeof(Point));
second_point_ptr->x = 5;
free(second_point_ptr);
}
The first declares an unnamed struct, and a type pStudentRecord that is a pointer to it. The second declares g_ppRecords to be a pointer to a pStudentRecord. In other words, a pointer to a pointer to a struct.
It's probably easier to think of the second as an "array of pointers". As such, g_ppRecords[0] may point to a pStudentRecord and g_ppRecords[1] to another one. (Which, in turn, point to a record struct.)
In order to add to it, you will need to know how it stores the pointers, that is, how one might tell how many pointers are stored in it. There either is a size somewhere, which for size N, means at least N * sizeof(pStudentRecord*) of memory is allocated, and g_ppRecords[0] through g_ppRecords[N-1] hold the N items. Or, it's NULL terminated, which for size N, means at least (N+1) * sizeof(pStudentRecord*) of memory is allocated and g_ppRecords[0] through g_ppRecords[N-1] hold the N items, and g_ppRecords[N] holds NULL, marking the end of the string.
After this, it should be straightforward to create or add to a g_ppRecords.
A struct is a compound data type, meaning that it's a variable which contains other variables. You're familiar with Objective C, so you might think of it as being a tiny bit like a 'data only' class; that is, a class with no methods. It's a way to store related information together that you can pass around as a single unit.
Typedef is a way for you to name your own data types as synonyms for the built-in types in C. It makes code more readable and allows the compiler to catch more errors (you're effectively teaching the compiler more about your program's intent.) The classic example is
typedef int BOOL;
(There's no built-in BOOL type in older ANSI C.)
This means you can now do things like:
BOOL state = 1;
and declare functions that take BOOL parameters, then have the compiler make sure you're passing BOOLs even though they're really just ints:
void flipSwitch(BOOL isOn); /* function declaration */
...
int value = 0;
BOOL boolValue = 1;
flipSwitch(value); /* Compiler will error here */
flipSwitch(boolValue); /* But this is OK */
So your typedef above is creating a synonym for a student record struct, so you can pass around student records without having to call them struct StudentRecord every time. It makes for cleaner and more readable code. Except that there's more to it here, in your example. What I've just described is:
typedef struct {
char * firstName;
char * lastName;
int id;
float mark;
} StudentRecord;
You can now do things like:
StudentRecord aStudent = { "Angus\n", "Young\n", 1, 4.0 };
or
void writeToParents(StudentRecord student) {
...
}
But you've got a * after the typedef. That's because you want to typedef a data type which holds a pointer to a StudentRecord, not typedef the StudentRecord itself. Eh? Read on...
You need this pointer to StudentRecord because if you want to pass StudentRecords around and be able to modify their member variables, you need to pass around pointers to them, not the variables themselves. typedefs are great for this because, again, the compiler can catch subtle errors. Above we made writeToParents which just reads the contents of the StudentRecord. Say we want to change their grade; we can't set up a function with a simple StudentRecord parameter because we can't change the members directly. So, we need a pointer:
void changeGrade(StudentRecord *student, float newGrade) {
student->mark = newGrade;
}
Easy to see that you might miss the *, so instead, typedef a pointer type for StudentRecord and the compiler will help:
typedef struct { /* as above */ } *PStudentRecord;
Now:
void changeGrade(PStudentRecord student, float newGrade) {
student->mark = newGrade;
}
It's more common to declare both at the same time:
typedef struct {
/* Members */
} StudentRecord, *PStudentRecord;
This gives you both the plain struct typedef and a pointer typedef too.
What's a pointer, then? A variable which holds the address in memory of another variable. Sounds simple; it is, on the face of it, but it gets very subtle and involved very quickly. Try this tutorial
This defines the name of a pointer to the structure but not a name for the structure itself.
Try changing to:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
} StudentRecord;
StudentRecord foo;
StudentRecord *pfoo = &foo;

Resources