Structure pointer pointing to different structure instance - c

struct first_struct
{
int a;
int b;
};
struct second_struct
{
char d;
int e;
};
struct second_struct second_ins = {'a',10};
struct first_struct first_ins = {20,12};
int main()
{
struct second_struct *pointer = &first_ins;
printf("%d\n",pointer->d);
return 0;
}
And I get an output of 20. Basically, I was trying to see that if I declare a structure pointer, and try to point this to an instance of another structure, what result do I get. Besides a warning from compiler for an incompatible pointer type, it builds and runs fine.
I was trying to understand how this operation was interpreted by compiler. Shouldnt this be undefined, or may be it is and I am just getting lucky with the result.

It's likely that both structs have the same element-wise alignment: sizeof(first_struct) == sizeof(second_struct) and: int e starts at the same offset in the struct as: int b
In other words, char d is effectively stored as an int in terms of layout. It's simply a lucky coincidence on your platform, and will not work portably.

Related

Get the same field from different structures using the same function in C

I want to have two structures in C, for example:
A:
typedef struct a
{
char *text;
int something;
}A;
and B:
typedef struct b
{
char *text;
float something_else;
}B;
Now, as far as I know, it is not possible to have a function which takes a void * parameter to get the text element from both structures. Am I wrong, is this possible in standard C?
Yes you can, using casting and the fact that the text element is the first element of both structures:
void f(void *t)
{
printf("%s\n", *((char **)t));
}
int main()
{
struct a AA = {"hello",3};
struct b BB = {"world",4.0};
f(&AA);
f(&BB);
return 0;
}
Note: Passing the address of the struct means it points to the address of text. This must then still be dereferenced one more time to get at the adress of the text itself, which is then passed to printf.
Edit: a cast to (void *) in the calls to f are not necessary (casts removed).

Kind of polymorphism in C

I'm writing a C program in which I define two types:
typedef struct {
uint8_t array[32];
/* struct A's members */
...
} A;
typedef struct {
uint8_t array[32];
/* struct B's members, different from A's */
...
} B;
Now I would like to build a data structure which is capable of managing both types without having to write one for type A and one for type B, assuming that both have a uint8_t [32] as their first member.
I read how to implement a sort of polymorphism in C here and I also read here that the order of struct members is guaranteed to be kept by the compiler as written by the programmer.
I came up with the following idea, what if I define the following structure:
typedef struct {
uint8_t array[32];
} Element;
and define a data structure which only deals with data that have type Element? Would it be safe to do something like:
void f(Element * e){
int i;
for(i = 0; i < 32; i++) do_something(e->array[i]);
}
...
A a;
B b;
...
f(((Element *)&a));
...
f(((Element *)&b));
At a first glance it looks unclean, but I was wondering whether there are any guarantees that it will not break?
If array is always the first in your struct, you can simply access it by casting pointers. There is no need for a struct Element. You data structure can store void pointers.
typedef struct {
char array[32];
} A;
typedef struct {
void* elements;
size_t elementSize;
size_t num;
} Vector;
char* getArrayPtr(Vector* v, int i) {
return (char*)(v->elements) + v->elementSize*i;
}
int main()
{
A* pa = malloc(10*sizeof(A));
pa[3].array[0] = 's';
Vector v;
v.elements = pa;
v.num = 10;
v.elementSize = sizeof(A);
printf("%s\n", getArrayPtr(&v, 3));
}
but why not have a function that works with the array directly
void f(uint8_t array[32]){
int i;
for(i = 0; i < 32; i++) do_something(array[i]);
}
and call it like this
f(a.array)
f(b.array)
polymorphism makes sense when you want to kepp
a and b in a container of some sorts
and you want to iterate over them but you dont want to care that they are different types.
This should work fine if you, you know, don't make any mistakes. A pointer to the A struct can be cast to a pointer to the element struct, and so long as they have a common prefix, access to the common members will work just fine.
A pointer to the A struct, which is then cast to a pointer to the element struct can also be cast back to a pointer to the A struct without any problems. If element struct was not originally an A struct, then casting the pointer back to A will be undefined behavior. And this you will need to manage manually.
One gotcha (that I've run into) is, gcc will also allow you to cast the struct back and forth (not just pointer to struct) and this is not supported by the C standard. It will appear to work fine until your (my) friend tries to port the code to a different compiler (suncc) at which point it will break. Or rather, it won't even compile.

How to use D structures from C code?

Could anyone explain me how to use D structures from C code? If I am trying to use it I receive such an error:
error: storage size of 'myStruct' isn't known
struct str_struct myStruct;
This is a structure:
extern(C) {
struct str_struct {
string str;
};
}
I use it in C like this : struct str_struct myStruct;
You have to duplicate the struct definition with all members in both languages (unless you want to refer to it only by pointer). C can't see a field list written in D.
D:
struct Foo {
int length;
int* data;
}
C:
typedef struct Foo {
int length;
int* data;
};
The tricky thing is to get long right. long in D is always 64 bits, so in C, that would be long long. Most other basic types translate pretty easily though: short=>short, int to int, char to char, pointers work the same way, etc.

array to structure casting

I have these three structures,
typedef struct serial_header {
int zigbeeMsgType;
int seqNumber;
int commandIdentifier;
int dest;
int src;
}serial_header_t;
typedef struct serial_packet {
serial_header_t header;
int data[];
} serial_packet_t;
and last one is
typedef struct readAttributePacket
{
int u8SourceEndPointId;
int u8DestinationEndPointId;
int u16ClusterId;
int bDirectionIsServerToClient;
int u8NumberOfAttributesInRequest;
int bIsManufacturerSpecific;
int u16ManufacturerCode;
int pu16AttributeRequestList[];
}readAttributePacket_t;
I am troubling with this code, i just want to cast the data[] array which reside in serial_packet_t into readAttributePacket_t structure.
I think the data[] should be
data[]={0x01,0x01,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
I need to cast those data to readAttributePacket_t structure. But this below code showing wrong.
void main()
{
int a[]= {0x32,0x00,0x31,0x69,0x69,0x00,0x00,0x01,0x01,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
int i;
readAttributePacket_t *p;
serial_packet_t *data;
data = (serial_packet_t*)&a;
for(i=0;i<20;i++){
printf(" %02x \n",a[i]);
}
p = (readAttributePacket_t *)&data->data;
printf("\nu8SourceEndPointId:%x \nu8DestinationEndPointId:%x \nu16ClusterId:%04x \nbDirectionIsServerToClient:%x \nu8NumberOfAttributesInRequest:%x \nbIsManufacturerSpecific:%x \nu16ManufacturerCode:%04x",p->u8SourceEndPointId,
p->u8DestinationEndPointId,
p->u16ClusterId,
p->bDirectionIsServerToClient,
p->u8NumberOfAttributesInRequest,
p->bIsManufacturerSpecific,
p->u16ManufacturerCode);
getch();
}
the output should be like
u8SourceEndPointId=01
u8DestinationEndPointId=01
u16ClusterId=0402
bDirectionIsServerToClient=00
u8NumberOfAttributesInRequest=02
bIsManufacturerSpecific=00
u16ManufacturerCode=0000
How could I get the pu16AttributeRequestList[] array into readAttributePacket_t structure, should like that,
pu16AttributeRequestList[0]=0000
pu16AttributeRequestList[1]=0001
You can't just cast an array to a structure because they're simply incompatible types. Due to memory alignment constraints, the compiler needs to insert padding between the fields of a structure, so the members are not located at the memory addresses you may expect. Solutions:
Portable but slower/harder to do manually (preferred): copy manually the fields of the structure to the array.
Shorter to write but GCC-specific: use the __attribute__((packed)) keyword to make GCC not introduce padding between struct fields.
Construct a union of 3 structs. all on equal memory space. then you dont even need to cast.
I think the only thing that you need to do in to remove the address operator from the casting statement.
data = (serial_packet_t*)a;
instead of
data = (serial_packet_t*)&a;
as far as I know, everything should work fine from here.

Return a `struct` from a function in C

Today I was teaching a couple of friends how to use C structs. One of them asked if you could return a struct from a function, to which I replied: "No! You'd return pointers to dynamically malloced structs instead."
Coming from someone who primarily does C++, I was expecting not be able to return structs by values. In C++ you can overload the operator = for your objects and makes complete sense to have a function to return your object by value. In C, however, you do not have that option and so it got me thinking what the compiler is actually doing. Consider the following:
struct MyObj{
double x, y;
};
struct MyObj foo(){
struct MyObj a;
a.x = 10;
a.y = 10;
return a;
}
int main () {
struct MyObj a;
a = foo(); // This DOES work
struct b = a; // This does not work
return 0;
}
I understand why struct b = a; should not work -- you cannot overload operator = for your data type. How is it that a = foo(); compiles fine? Does it mean something other than struct b = a;? Maybe the question to ask is: What exactly does the return statement in conjunction to = sign do?
You can return a structure from a function (or use the = operator) without any problems. It's a well-defined part of the language. The only problem with struct b = a is that you didn't provide a complete type. struct MyObj b = a will work just fine. You can pass structures to functions as well - a structure is exactly the same as any built-in type for purposes of parameter passing, return values, and assignment.
Here's a simple demonstration program that does all three - passes a structure as a parameter, returns a structure from a function, and uses structures in assignment statements:
#include <stdio.h>
struct a {
int i;
};
struct a f(struct a x)
{
struct a r = x;
return r;
}
int main(void)
{
struct a x = { 12 };
struct a y = f(x);
printf("%d\n", y.i);
return 0;
}
The next example is pretty much exactly the same, but uses the built-in int type for demonstration purposes. The two programs have the same behaviour with respect to pass-by-value for parameter passing, assignment, etc.:
#include <stdio.h>
int f(int x)
{
int r = x;
return r;
}
int main(void)
{
int x = 12;
int y = f(x);
printf("%d\n", y);
return 0;
}
When making a call such as a = foo();, the compiler might push the address of the result structure on the stack and passes it as a "hidden" pointer to the foo() function. Effectively, it could become something like:
void foo(MyObj *r) {
struct MyObj a;
// ...
*r = a;
}
foo(&a);
However, the exact implementation of this is dependent on the compiler and/or platform. As Carl Norum notes, if the structure is small enough, it might even be passed back completely in a register.
The struct b line doesn't work because it's a syntax error. If you expand it out to include the type it will work just fine
struct MyObj b = a; // Runs fine
What C is doing here is essentially a memcpy from the source struct to the destination. This is true for both assignment and return of struct values (and really every other value in C)
As far as I can remember, the first versions of C only allowed to return a value that
could fit into a processor register, which means that you could only return a pointer to
a struct. The same restriction applied to function arguments.
More recent versions allow to pass around larger data objects like structs.
I think this feature was already common during the eighties or early nineties.
Arrays, however, can still be passed and returned only as pointers.
There is no issue in passing back a struct. It will be passed by value
But, what if the struct contains any member which has a address of a local variable
struct emp {
int id;
char *name;
};
struct emp get() {
char *name = "John";
struct emp e1 = {100, name};
return (e1);
}
int main() {
struct emp e2 = get();
printf("%s\n", e2.name);
}
Now, here e1.name contains a memory address local to the function get().
Once get() returns, the local address for name would have been freed up.
SO, in the caller if we try to access that address, it may cause segmentation fault, as we are trying a freed address. That is bad..
Where as the e1.id will be perfectly valid as its value will be copied to e2.id
So, we should always try to avoid returning local memory addresses of a function.
Anything malloced can be returned as and when wanted
yes, it is possible we can pass structure and return structure as well. You were right but you actually did not pass the data type which should be like this struct MyObj b = a.
Actually I also came to know when I was trying to find out a better solution to return more than one values for function without using pointer or global variable.
Now below is the example for the same, which calculate the deviation of a student marks about average.
#include<stdio.h>
struct marks{
int maths;
int physics;
int chem;
};
struct marks deviation(struct marks student1 , struct marks student2 );
int main(){
struct marks student;
student.maths= 87;
student.chem = 67;
student.physics=96;
struct marks avg;
avg.maths= 55;
avg.chem = 45;
avg.physics=34;
//struct marks dev;
struct marks dev= deviation(student, avg );
printf("%d %d %d" ,dev.maths,dev.chem,dev.physics);
return 0;
}
struct marks deviation(struct marks student , struct marks student2 ){
struct marks dev;
dev.maths = student.maths-student2.maths;
dev.chem = student.chem-student2.chem;
dev.physics = student.physics-student2.physics;
return dev;
}
You can assign structs in C. a = b; is valid syntax.
You simply left off part of the type -- the struct tag -- in your line that doesn't work.
struct emp {
int id;
char *name;
};
struct emp get() {
char *name = "John";
struct emp e1 = {100, name};
return (e1);
}
int main() {
struct emp e2 = get();
printf("%s\n", e2.name);
}
works fine with newer versions of compilers.
Just like id, content of the name gets copied to the assigned structure variable.
struct var e2 address pushed as arg to callee stack and values gets assigned there. In fact, get() returns e2's address in eax reg. This works like call by reference.
#include <stdio.h>
struct emp {
int id;
char *name; /* This must point to valid memory, or replace with an array that holes the data, like this char name[128] */
};
struct emp bad() {
static char name[] = {'J', 'o', 'h', 'n', '\0'}; /* static enforces this array to be stored globally and not in the local stack which would not be valid after the function returns */
struct emp e1 = {404, name};
return (e1);
}
int main() {
struct emp e2 = bad();
printf("%s\n", e2.name);
}

Resources