?
Solved

passing structures to function

Posted on 2005-04-19
18
Medium Priority
?
421 Views
Last Modified: 2010-04-15
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.

0
Comment
Question by:b123coder
  • 7
  • 6
  • 2
  • +2
18 Comments
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 13821363
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
 
LVL 45

Expert Comment

by:sunnycoder
ID: 13821423
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
 

Author Comment

by:b123coder
ID: 13821591
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 45

Expert Comment

by:sunnycoder
ID: 13821668
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
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 13822275
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
 

Author Comment

by:b123coder
ID: 13822712
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
 
LVL 45

Expert Comment

by:sunnycoder
ID: 13822719
you allocated no memory for data1
0
 

Author Comment

by:b123coder
ID: 13822764

 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
 

Author Comment

by:b123coder
ID: 13822768
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
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 13822779
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
 

Author Comment

by:b123coder
ID: 13822787
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
 
LVL 45

Expert Comment

by:sunnycoder
ID: 13822858
your first printf is apparently before allocation
0
 

Author Comment

by:b123coder
ID: 13823359
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
 

Expert Comment

by:medevil
ID: 13828778
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
 
LVL 45

Expert Comment

by:sunnycoder
ID: 13830133
>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
 

Author Comment

by:b123coder
ID: 13830948
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
 

Assisted Solution

by:medevil
medevil earned 120 total points
ID: 13833251
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
 
LVL 45

Accepted Solution

by:
sunnycoder earned 120 total points
ID: 13839305
>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

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.
Suggested Courses

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question