How to make a shallow copy of entire structure? [duplicate] - c

I want to copy an identical struct into another and later on use it as a comparance to the first one. The thing is that my compiler gives me a warning when Im doing like this! Should I do it in another way or am I doing this wrong:
In header File:
extern struct RTCclk
{
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t mday;
uint8_t month;
uint8_t year;
}
RTCclk;
In C file:
struct RTCclk RTCclk;
struct RTCclk RTCclkBuffert;
void FunctionDO(void)
{
... // Some Code
/* Copy first struct values into the second one */
memcpy(&RTCclk, &RTCclkBuffert, sizeof RTCclk);
}

For simple structures you can either use memcpy like you do, or just assign from one to the other:
RTCclk = RTCclkBuffert;
The compiler will create code to copy the structure for you.
An important note about the copying: It's a shallow copy, just like with memcpy. That means if you have e.g. a structure containing pointers, it's only the actual pointers that will be copied and not what they point to, so after the copy you will have two pointers pointing to the same memory.

Your code is correct. You can also assign one directly to the other (see Joachim Pileborg's answer).
When you later come to compare the two structs, you need to be careful to compare the structs the long way, one member at a time, instead of using memcmp; see How do you compare structs for equality in C?

copy structure in c you just need to assign the values as follow:
struct RTCclk RTCclk1;
struct RTCclk RTCclkBuffert;
RTCclk1.second=3;
RTCclk1.minute=4;
RTCclk1.hour=5;
RTCclkBuffert=RTCclk1;
now RTCclkBuffert.hour will have value 5,
RTCclkBuffert.minute will have value 4
RTCclkBuffert.second will have value 3

Also a good example.....
struct point{int x,y;};
typedef struct point point_t;
typedef struct
{
struct point ne,se,sw,nw;
}rect_t;
rect_t temp;
int main()
{
//rotate
RotateRect(&temp);
return 0;
}
void RotateRect(rect_t *givenRect)
{
point_t temp_point;
/*Copy struct data from struct to struct within a struct*/
temp_point = givenRect->sw;
givenRect->sw = givenRect->se;
givenRect->se = givenRect->ne;
givenRect->ne = givenRect->nw;
givenRect->nw = temp_point;
}

Your memcpy code is correct.
My guess is you are lacking an include of string.h. So the compiler assumes a wrong prototype of memcpy and thus the warning.
Anyway, you should just assign the structs for the sake of simplicity (as Joachim Pileborg pointed out).

memcpy expects the first two arguments to be void*.
Try:
memcpy( (void*)&RTCclk, (void*)&RTCclkBuffert, sizeof(RTCclk) );
P.S. although not necessary, convention dictates the brackets for the sizeof operator. You can get away with a lot in C that leaves code impossible to maintain, so following convention is the mark of a good (employable) C programmer.

I think you should cast the pointers to (void *) to get rid of the warnings.
memcpy((void *)&RTCclk, (void *)&RTCclkBuffert, sizeof RTCclk);
Also you have use sizeof without brackets, you can use this with variables but if RTCclk was defined as an array, sizeof of will return full size of the array. If you use use sizeof with type you should use with brackets.
sizeof(struct RTCclk)

Related

What is the purpose of creating a struct with only one field

On the project in my company I saw a couple of times people creating a struct that contains only one element.
the latest one is added, in this example ipAddr is another struct( a good explanation to the case when ipAddr is an array is given by 'Frerich Raabe' but unfortunately thats not the case here)
typedef struct
{
ipAddr ip;
} Record;
I guess if the code is changing and in its beginning this makes sense since more fields can be easily added and the code can be easily manipulated to support the new fields, but this is a project started a long time ago written according to a design so I dont think its the issue here.
Why would one create a struct of one field then?
I can think of a couple reasons:
In case more fields may be needed later. This is somewhat common.
To deliberately make the outer type incompatible with the inner type.
For an example of the second, imagine this:
typedef struct
{
char postal_code[12];
} Destination;
In this case, the Destination is fully specified by the postal code, yet this will let us define functions like this:
int deliver(const char* message, const Destination* to);
This way, no user can inadvertently call the function with the two arguments reversed, which they could easily do if they were both plain strings.
A common reason for a struct with just one field is that the single field is an array, and you'd like to be able to define functions returning such array values. Consider e.g.
typedef unsigned char ipAddr[4];
void f(ipAddr ip); /* OK */
ipAddr g(void); /* Compiler barfs: cannot return array. */
This can be resolved by introducing a struct with a single member of type ipAddr:
typedef unsigned char ipAddr[4];
typedef struct {
ipAddr ip;
} Record;
void f(Record ip); /* OK */
Record g(void); /* Also OK: structs can be returned by value. */
However, even passing arrays to functions is problematic: you don't actually pass the array, you pass a pointer (the type "decays" into a pointer). Imagine f declared above would need to create a copy of the given IP address:
typedef unsignd char ipAddr[4];
void f(ipAddr ip) {
ipAddr *a = malloc(sizeof(ip));
/* ... */
}
This only happens to work with 32bit builds because the size of a pointer is the same (4 bytes) as the size of an array of four unsigned char values. A 64bit build (or a differently sized array) would exhibit a bug, either allocating too much or too little memory. This happens because inside f, ip is of type unsigned char *, i.e.a pointer. A struct helps with this, since it doesn't decay.

Location of the struct when only the location of a member is given

Let us assume there is a struct with multiple members. The struct members are initialized with some values. The memory location of a specific member is given. Assume that you don't know the other members, their types, the ordering of members etc. Is there a way to know the memory location of the struct itself?
Is this problem called a specific name?
If you know the name of the struct, simply use offsetof
struct my_struct {
const char *name;
struct list_node list;
};
int main() {
struct my_struct t;
struct list_node* pl = &t.list;
size_t offset = offsetof(struct my_struct, list); //here
struct my_struct* pt = (struct my_struct*)((unsigned char*)pl-offset); //and here
}
If offsetof is not viable for what you're doing, then no, there's no other way. Offsetof can alternatively be written in standard C, but there's absolutely no good reason to do that.
If you know the structure type, then all you need is an offset of the field within the structure, subtract it from the member address and typecast result to pointer to the structure. For a practical implementation see FreeBSD's implementation of __containerof().
Hi Everyone I found the answer this
Cast a null pointer to the struct. You can get the offset by casting the resulting address(Offset) to a char*
(char *)(&((struct *)0)->member))
You could do any type*. But char* guarantees it's always the word size.
This should be how offsetof() is written as well

C how to modify memory of structs that are inside other structs

If I have two structs:
typedef struct{
unsigned int time;
double rate;
}quote;
typedef struct{
unsigned int freeSlots;
unsigned int end;
unsigned int start;
unsigned int currSize;
unsigned int maxSize;
unsigned int startAt;
//unsigned int currIndex;
quote quoteBuffer[1];
}cbuf;
And I wanted to make a function that would modify the size of the quoteBuffer array inside cbuf, how exactly would I go about doing that? I have tried a few approaches but none have worked so far. I keep returning to the same format of:
quote *newQuoteBuffer = malloc(sizeof(quote) * newSize);
And if I already have an existing cbuf somewhere (for example, we will call it "a" where a is the pointer to the cbuf):
a->quoteBuffer = newQuoteBuffer;
But obviously this doesn't work. Any hints?
This:
quote quoteBuffer[1];
should be:
quote *quoteBuffer;
Then the assignment will work.
Dereferencing quote looks like this:
a->quoteBuffer->time;
If you later have multiple elements of quote allocated with malloc() you can access them like this:
a->quoteBuffer[i].time;
If you are not sure of how many elements will go into the quoteBuffer, maintain a linked list of the same. For that
quote *quoteBuffer;
And keep adding or removing the elements to/from the buffer as required.
I think you're missing the point of why someone would have the last element of a struct as a single element array. This is a trick that's used in old C code as a way to make the struct size variable length.
You can write code such as this:
Bitmapset *p = malloc(offsetof(Bitmapset, quoteBuffer) + n * sizeof(quote));
Then you write code like this:
p->quoteBuffer[0]
up to:
p->quoteBuffer[n-1]
You do not want to assign a pointer directly to quoteBuffer, as you guessed.
So, why would you want to declare quoteBuffer as:
quote quoteBuffer[1];
instead of
quote* quoteBuffer;
?
It's because you do not wanna to have a separate allocation for quoteBuffer. A single allocation can be used for the entire cbuf, including the inline quote array.
There are two approaches. One is to use a pointer in cbuf, as others have mentioned, by changing
quote quoteBuffer[1];
to
quote* quoteBuffer;
The other is to resize the cbuf:
#include <stddef.h> // for offsetof
struct cbuf* realloc_cbuf(struct cbuf* cbufp, size_t nquotes)
{
struct cbuf* new_cbufp = realloc(cbufp, offsetof(struct cbuf, quoteBuffer) + nquotes * sizeof *cbufp->quoteBuffer);
if (!new_cbufp)
{
// handle out of memory here. cbufp is still intact so free it if you don't need it.
}
return new_cbufp;
}
void elsewhere(void)
{
struct cbuf* acbuf = NULL;
acbuf = realloc_cbuf(1);
acbuf = realloc_cbuf(10);
// etc.
}

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;

variable declaration problem inside struct

I declared a Normal Structure In C:
typedef struct arr_struct{
int* original;
int size;
int first[size/2];
int second[size-(size/2)];
};
when compile it gives me:
test.c:11: error: ‘size’ undeclared here (not in a function)
any explanation?
You can't define arrays based on a variable size. The size has to be known at compile time. You'll need to make first and second pointers and dynamically allocate them once size is known.
You're getting the error message because you're trying to use the size member of the struct illegally. For one thing, the struct type definition isn't complete until the closing }, so until then the compiler doesn't know that there's a size member within the struct. For another, you cannot refer to a struct member without a struct instance; when you used the expression size the declarators for first and second, the compiler was looking for a variable named size outside of the struct definition.
It is possible to use a VLA within a struct type, but that's really not the approach you want to take here if you're doing what I think you're doing. Better to make first and second pointers to int and allocate them as necessary (as demonstrated by a couple of the answers above).
int val;
scanf("%d",&val);
int a[val];
The above code actually compiles and runs in my gcc compiler.
The reason for not working inside a struct could be due to the lining up of elements inside a struct whose size can't be determined at compile time. I am not fully sure about it though.
An implementation and usage for what miked said could be (without error checking):
typedef struct
{
int size;
int* first;
int* second;
} arr_struct;
// Prepare an arr_struct for use.
arr_struct foo;
foo.size = 1337;
foo.first = malloc(sizeof(int)*foo.size);
foo.second = malloc(sizeof(int)*(foo.size-foo.size/2));
Do remember to free(foo.first) and free(foo.second) when you're done, though!
The size you provide for an array needs to be a constant expression. You have a couple of choices. One would be to include a couple of pointers, and allocate the space dynamically:
typedef struct {
int* original;
int size;
int *first;
int *second;
} arr_struct;
Another possibility would be to use only one array, and create a pointer to the proper point in it:
typedef struct {
int* original;
int size;
int *second;
int first[];
} arr_struct;
This uses a flexible array member, which is new with C99 -- if you're using an out of date C compiler (e.g., MS VC++) it might not be supported directly1. In any case, this still requires dynamic allocation, but lets you do one large allocation for all the data instead of three separate allocations (one for the struct, and one each for first and second).
arr_struct *my_struct = malloc(sizeof(*my_struct) + size * sizeof(int));
my_struct->second = my_struct->first + size/2;
As an aside, note the syntax for typedef -- as it was, your typedef wasn't defining a name at all.
1The workaround is trivial though -- just define first with a size of 1 and subtract 1 from size in your allocation:
arr_struct *my_struct = malloc(sizeof(*my_struct) + (size-1) * sizeof(int));
In theory, this isn't required to work, but in fact it's just fine with all real compilers, at least AFAIK.

Resources