• C

passing structures to function

hello,
                I want to send 3 structures to a function in another source file. Is it possible to have all 3 structures in a unsigned char *alldata variable and send it to function?
              How can i do that? as they are structures not strings so that strcpy like thing in case of strings will not work at here. which function then i use?
             Please Kindly remember that i require this on LINUX machines using gcc.

b123coderAsked:
Who is Participating?
 
sunnycoderConnect With a Mentor Commented:
>data1=malloc(2 * sizeof(struct other1) +1);
assume that system returned you memory starting from location 1000

>memset(data1,'\0',sizeof(data1));
>printf("data1 address=%p\n",data1);
>data1=fills(data1);
fine so far ... you copied a struct at location 1000, let us assume that struct was 10 bytes long and we are supposed to copy the next struct from 1010

>data1=data1+sizeof(struct other1);
You moved data1 to location 1010 ... Now if you wish to access the struct you copied into locations 1000-1010, how can you do it!!!

>printf("data1 address=%p\n",data1);
>data1=fillt(data1);
again copying a struct starting from 1010, ok

>memcpy(&oth1,data1+sizeof(struct other1),sizeof(struct other1));
data1 is 1010, struct otehr1 is 10 bytes long, so you are copying from 1020!!! this was not where you stored it

>printf("oth1.num=%d, oth1.addr=%s\n",oth1.num,oth1.addr);
no wonder the values here are incorrect
0
 
brettmjohnsonCommented:
It is not necessary to coerce the structures to char *.  Simply pass all three as three
separate parameters to the function:

struct foo f;
struct bar b;
struct xyzzy x;

/* prototype for function that lives in the other file.
 * this should propbably be in a common .h file
 */
int otherfunc(struct foo *, struct bar *, struct xyzzy *);
...
int val = otherfunc(&f, &b, &x);
...

/* other file */
int otherfunc(struct foo * f, struct bar * b, struct xyzzy *x)
{
      ...
      return (f->val + b->num + x->total);
}
0
 
sunnycoderCommented:
brett is right ... passing them as three separate parameters is likely to be the best option ... If you still wish to club them, there are a couple of clean ways and as usual plenty of unclean ways ...

You can declare a new struct type

struct big_one {
   struct a * first;
   struct b * second;
   struct c * third;
};

You can set the pointers to your struct and pass pointer t big_one to your function ...

Yet another way would be to use struct as elements of big_one rather than pointers ... Here however, you will have to write code to copy structs and it is likely to be slower ... Also, if you have multiple copies of the same information, propagating a change to every copy is a big hole to dig for yourself
0
Improve Your Query Performance Tuning

In this FREE six-day email course, you'll learn from Janis Griffin, Database Performance Evangelist. She'll teach 12 steps that you can use to optimize your queries as much as possible and see measurable results in your work. Get started today!

 
b123coderAuthor Commented:
I just want to see this simulatory thing which is nothing but actual packet working in kernel and building packet with all header structures and data in kernel.  Thats why i require a solution to send structures in unsigned char *data variable and retreive it without any problem.
0
 
sunnycoderCommented:
You cam use memcpy/memmove to copy memory locations ... They would not be accessible from within the kernel, look for kernel equivalents of these
0
 
PaulCaswellCommented:
It sounds like you are trying to simulate network traffic. The answer is to roll the structures up into another, generic structure that can then be seen, in transit, as just a data block with a length.

typedef struct Packet
{
 long length;
 unsigned char data[];
}

You can then allocate it at one place:

 long length = sizeof(Packet) + sizeof(structure1) + sizeof(structure2);
 Packet * packet = (Packet*) malloc(length);
 if ( packet != NULL )
 {
   packet->length = length;
   // Copy in the data.
   ...
 }

You can now send a Packet anywhere and only the receiver needs to know its deeper structure, the transporter only needs to know that it is a packet.

Paul
0
 
b123coderAuthor Commented:
hello all,
         I did some programming on that with 2 structures. I try to add both structures in unsigned char *data then try to get first one from that data variable but unable to get it please correct my program

#include <stdio.h>
#include <string.h>
struct other1{
int num;
char *addr;
};

struct other2{
int num;
char *addr;
};

unsigned char *fills(unsigned char *d)
{
struct other1 o1;
o1.num=100;
o1.addr="FILLS";
printf("sizeof other1 o1=%d\n",sizeof(o1));
memcpy(d,&o1,sizeof(struct other1));
return d;
}

unsigned char *fillt(unsigned char *d1)
{
struct other2 o2;
o2.num=200;
o2.addr="FILLT";
printf("sizeof other2 o2=%d\n",sizeof(o2));
memcpy(d1,&o2,sizeof(struct other2));
return d1;
}

int main()
{
struct other1 oth1;
unsigned char *data1;
printf("data1 address=%p\n",data1);
data1=fills(data1);
data1=data1+sizeof(struct foo);
printf("data1 address=%p\n",data1);
data1=fillt(data1);
printf("data1 address=%p\n",data1);

memcpy(&oth1,data1+sizeof(struct other1),sizeof(struct other1));
printf("oth1.num=%d, oth1.addr=%s\n",oth1.num,oth1.addr);
//require output as oth1.num=100, oth1.addr=FILLS
return 0;
}

I am getting output as=>
data1 address=0x804848a
sizeof other1 o1=8
Segmentation fault

0
 
sunnycoderCommented:
you allocated no memory for data1
0
 
b123coderAuthor Commented:

 I am confused about how much space to allocate data1 in above program. require help
becasue i added following statements but got segmentation fault

data1=malloc(2 * sizeof(struct other1) +1);
memset(data1,'\0',sizeof(data1));
0
 
b123coderAuthor Commented:
my code ofr main function is

int main()
{
struct other1 oth1;
unsigned char *data1;
data1=malloc(2 * sizeof(struct other1) +1);
memset(data1,'\0',sizeof(data1));
printf("data1 address=%p\n",data1);
data1=fills(data1);
data1=data1+sizeof(struct other1);
printf("data1 address=%p\n",data1);
data1=fillt(data1);
printf("data1 address=%p\n",data1);

memcpy(&oth1,data1+sizeof(struct other1),sizeof(struct other1));
printf("oth1.num=%d, oth1.addr=%s\n",oth1.num,oth1.addr);
//require output as oth1.num=100, oth1.addr=FILLS
return 0;

}
0
 
PaulCaswellCommented:
You are allocating room for two structures but these structures only contain pointers to the data, not the data itself. In a case like this yoyu need to allocat a large block and ensure that it doesnt overflow.

Paul
0
 
b123coderAuthor Commented:
ok so malloc(1024) to data1 solves segmentation fault
BUT still output is
data1 address=0x8049788
sizeof other1 o1=8
data1 address=0x8049790
sizeof other2 o2=8
data1 address=0x8049790
oth1.num=0, oth1.addr=(null)
0
 
sunnycoderCommented:
your first printf is apparently before allocation
0
 
b123coderAuthor Commented:
I want to get correct output at last line of output in program. why its not priting correct results when i did
 memcpy(&oth1,data1+sizeof(struct other1),sizeof(struct other1));
printf("oth1.num=%d, oth1.addr=%s\n",oth1.num,oth1.addr);
0
 
medevilCommented:
in your main() function, there is:

memcpy(&oth1,data1+sizeof(struct other1),sizeof(struct other1));
printf("oth1.num=%d, oth1.addr=%s\n",oth1.num,oth1.addr);
//require output as oth1.num=100, oth1.addr=FILLS
return 0;

you are telling memcpy to copy from data1+sizeof(struct other1) which is currently not set.
if you think data1 as an array, you have filled (with fills() and fillt() ) data1[0] and data1[1] but not data1[2] (wich is the address you are memcpy()-ing to oth1)

try with:
memcpy(&oth1, data1, sizeof(struct other1));

note also that the operator sizeof() returns the size of the variable, not the allocated memory, ie:

char *x = NULL;
printf("sizeof(x) is: %d\n", sizeof(x));
x = malloc(30);
printf("sizeof(x) is: %d\n", sizeof(x));

output is:
sizeof(x) is: 4
sizeof(x) is: 4
0
 
sunnycoderCommented:
>printf("data1 address=%p\n",data1);
>data1=fills(data1);
You copied other1 to data1

>data1=data1+sizeof(struct foo);
What is this struct foo? If you meant other struct other1, then you have lost the starting location of original data1 (though it can still be recovered by subtracting sizeof other1, but this is a dangerous proprosition)

>printf("data1 address=%p\n",data1);
>data1=fillt(data1);
If the foo line was an error then you have overwritten previous copy

>printf("data1 address=%p\n",data1);
>memcpy(&oth1,data1+sizeof(struct other1),sizeof(struct other1));
stuct other1 was at original data1 and not data1+ something

If you follow common good code writing practices, this code would be far more easier to read and would also be easier for you to write
0
 
b123coderAuthor Commented:
to medevil,
        memcpy(&oth1, data1, sizeof(struct other1));
this gives me whatever filled in fillt() but before that i also filled data with fills() how can i access that?

to sunnycoder,
              Yes i have added foo and posted same code after removing that one but forgot to change foo with other1. If you check my later posts i corrected that by replacing foo with other1

      I am not getting when i memcpy structs to data1 then how pointer moves in data1. Please explain me might be i am missing that thats why not able to print results of fills() in main.
0
 
medevilConnect With a Mentor Commented:
This is pointer arithmetic... ;)

this example may help you:

suppose we have the following struct:

struct your_data {
   int x;
   char* y;
}

and the following code:

struct your_data *data;
struct your_data *pointer;
unsigned char* uc_pointer;

/*
  malloc allocates a size of 4 + 4 bytes * 5 elements.
  note that char* is only a pointer, so if you would like to
  use functions like memcpy or memmove or others, you should
  allocate enough memory for that pointer.
*/
data = malloc(sizeof(struct your_data)*3);

/* check if data was allocated */
if (!data){
   printf("malloc() failed, error code is: %d\n", errno);
   return -1;
}

/* set all elements to zero */
memset(data, 0, sizeof(struct your_data)*3);

/* you can use the allocated space in many ways: */
/* 1. Array: */
data[0].x = 1;
data[1].x = 2;

// data[3].x = 4;

/*
   Note that the last commented code is invalid.
   Array indexes start with 0 so the last
   element we can access without segfaults is 2.
*/

/* 2. Pointers: */
pointer = data+1;

pointer->x = 5; /* this is like data[1] */

pointer++; /* this is valid */
pointer->x = 6;

pointer--;
/* if you try to printf() pointer->x it will print 5 */

/* now note this pointer: */
uc_pointer = (unsigne char*)data;
uc_pointer++;

/*
   this is DANGEROUS!
   sizeof(unsigned char*)   and   sizeof(struct your_data)  
   are not supposed to be equal, so you can overwrite
   parts of data.

   this, instead, is valid:
*/

uc_pointer = (unsigne char*)(data+1);
/*
   you can safely cast the: unsigned char*
   back to: struct your_struct
   and use that.

   now a little examples about the "y" variable in the struct:
*/

data[0].y = "TEST";
data[1].y = strdup(data[1]);

/*
   if you try printf() of data[0].y and data[1].y
   they will succeed.
   now look at these, the first will succeed,
   while the second will segfault. why?
*/

memcpy(data[2].y, "a", sizeof(data[2].y));
// memcpy(data[2].y, data[1], strlen(data[1]);

when we called malloc() it has allocated 8bytes * 3 (24 total bytes).
you can use these 24bytes as you want, no matter what you store in...
for example, you can use data like this:
(no matter if it was declared as a struct your_struct,
they are ONLY pointer to allocated memory)

memcpy(data, "a <24 bytes string", 18);
printf("%s", data);

if you have more question, just ask.. ;)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.