Okay. So I have the following struct:
struct pkt {
int seqnum;
int acknum;
int checksum;
char payload[20];
};
Now I have the following variables:
struct pkt packet;
struct pkt* packets[1000];
Now after a few manipulations of packet
I am trying to assign it to an array cell as follows:
packets[counter++] = (pkt*)&packet;
But that is somehow changing all the cells of the array upon a new assignment to the value of the new assignment.
What am I doing wrong?
I have just started off with C, so I am not so familiar with pointers and addresses.
EDIT: The function in which the assignment is being done:
void A_output(struct msg message)
{
struct pkt packet;
packet.acknum = 0;
packet.seqnum = 0;
memset(&packet.payload, '\0', 20);
memcpy((char*)&packet.payload, (char*)&message.data, 20);
memset(&packets[counter]->payload, '\0', 20);
packets[counter++] = (pkt*)&packet;
printAll();
if(nextseq < winbase + winsize) {
packets[nextseq]->seqnum = nextseq;
setChecksum(packets[nextseq]);
tolayer3(0, *packets[nextseq]);
if(winbase == nextseq)
starttimer(0, increment);
nextseq++;
}
}
Since the value is coming as a parameter of a function, doesn't it have a new memory address every time?
void A_output(struct msg message)
{
struct pkt packet;
[...]
packets[counter++] = (pkt*)&packet;
This last line assigns the address of a variable with automatic storage duration (a local variable) to an object with static storage duration (a global). Once your function exits, the variable with automatic storage duration doesn't exist anymore, therefore the pointer doesn't point to a valid location. Using this pointer later is undefined behavior, but it's quite likely that your function reuses the same memory location for your struct pkt packet
every time it is invoked, leading to the behavior you describe.
What you have to do is for example allocate memory for every element in packets
with malloc()
or new
:
struct pkt *packet = malloc(sizeof *packet); // C style
// or:
pkt *packet = new pkt(); // C++ style
[...] // fill *packet
packets[counter++] = packet;
Don't forget to free()
(C) or delete
(C++) all the packets when you're done.
On a side note, in your original code, the cast (pkt*)
is redundant. &packet
already has the type struct pkt *
. But as this is wrong anyways, it doesn't matter much here.
Well, all the cells in the array have the value of &packet
, which is a single value. They all point to the same address, so of course they all point to the same value.
You can dynamically allocate the memory, or much better, just make packets
a pkt[]
- an array of regular packets and then assignment to one of the cells will preform copy of all the values to another memory, not copy of pointer.
As for the question if packet
always has the same address, I cannot know for sure (My guess is that it does) but you could check - print the value of &packet
every time the function is called and see if it changes.
P.S. packet
isn't a function argument, but a local function variable.
packets[0] = &pkt;
Gives
+-----+ +-------+
| 0 | ========> | [pkt] |
+-----+ +-------+
Then
packets[1] = &pkt;
Gives
+-------+ +----------+
| 0 | ==========> | [pkt] |
+-------+ ||=> +----------+
| 1 | =======*
+-------+
There is one underlying object (pkt), which is referred to in two places in the array.
If you want their values to be distinct, then make the array an array of full members.
struct pkt packets[1000];
It looks like you're attempting to create an array of structures. The below code snippet creates a local array of structures which each contain an array of integers.
The method acts on the array of structures individually, assigning unique values to the integer array inside.
// Structure definitions
#define NUM_OF_VALUES 2
#define NUM_OF_STRUCTS 5
typedef struct {
uint value[NUM_OF_VALUES];
} Test_Struct_t;
// local object
static Test_Struct_t struct_array[NUM_OF_STRUCTS];
// Function settings values in local object.
void struct_foo(void)
{
for (uint idx = 0; idx < NUM_OF_STRUCTS; idx++)
{
for (uint jdx = 0; jdx < NUM_OF_VALUES; jdx++)
{
struct_array[idx].value[jdx] = (idx + jdx);
}
}
}
Since the value is coming as a parameter of a function, doesn't it
have a new memory address every time?
The function parameter(s) will be pushed to the stack when the function is called. If you want the variable you are parsing to retain its value after you operate on it, use a pointer argument instead.