I have gone through this very good article
https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule
but I didn't understood of aliasing with union, what I know about aliasing is with char/ unsigned char, which is a compiler exception according to this article. so , how I used to do aliasing with char/ unsigned char is like,
// lets say I have struct blah , having int member non_sense, cmmn_sense, intelligence...
struct blah *foo, *foo2;
unsigned char buffer [512];
foo = (struct blah *) (buffer+0);
//now accessing members
foo->non_sense = -1;
foo->non_snese = 0;
foo->intelligence =1;
// now we can use another struct after that ..
foo2 = (struct blah*) (buffer + sizeof(struct blah));
Please correct me if I am wrong some where :)
Q.So how can I do the same with union?
NOTE I didn't encountered with union much, so I don't know its proper use too.
I have also searched for aliasing with enum, but didn't understood much ,
Q.If possible with enum how will we do that?
Sorry for my English, not that good and please openly suggest correction for my misconception or terminology in my question to correct ...
Yes, almost any pointer (including your examples) is unsafe (except if it accessed by char).
Below is safe (access by char pointer):
struct blah x;
char *y = (char *)&x;
for(size_t i = 0; i < sizeof(x); i++)
printf("[%zu] = %hhd\n", i, y[i];
The correct way is to memcpy buffer into the struct or to have char array as one of the union members.
struct a
{
int a;
short b;
char x[2];
double z[3];
};
union b
{
unsigned char buffer[512];
struct a sa[512/32];
};
double foo(char *x)
{
struct a c;
memcpy(&c, x, sizeof(c));
return c.z[0];
}
double bar(void)
{
union b c;
read_from_uart(&c, 512);
return c.sa[5].z[1];
}
Q.If possible with enum how will we do that?
Enum is an integer. Same rules as for integers.
Related
My question is we do padding to align structures.
typedef struct structb_tag
{
char c;
int i;
} structb_t;
Here we use 8 bytes. Why can't we use the 3 bytes that lot?
Why cant we use the 3 bytes
You could.
To do so measure the size your implementation allocates for a struct and then make it a union adding a char-array of exactly the size measured and there you go.
Assuming this
typedef struct structb_tag
{
char c;
int i;
} structb_t;
is created using eight bytes, that is sizeof (structb_t) evaluates to 8, change it to the following
typedef union unionb_tag
{
char bytes[8];
struct
{
char c;
int i;
} structb;
}
More reliable, in terms of portability and also robustness, would be this:
typedef union unionb_tag
{
struct structb_tag
{
char c;
int i;
} structb;
char bytes[sizeof (struct structb_tag)];
}
If you are using GCC and space is the most important thing for you instead of speed (which padding provides) you could just request the compiler to not do the padding, struct __attribute__((__packed__)) mystruct, padding is the way for compiler to align structures in the natural for faster access.
You can always take the pointer to the structure convert it to a byte pointer and access any byte of that structure.This is dangerous way, though.
The padding are implementation dependent, which are not defined by the standard, you cannot not use them as there is no way to reference the padding bytes.
Yes, you can.
typedef struct structb_tag
{
char c;
char pad[3];
int i;
} structb_t;
structb_t test;
test.pad[0] = 'a';
In short, we can use that three bytes.
The reason why we need 3 bytes padding is for memory usage optimization, so the compiler will help us add an gap between c and i. So when you use
typedef struct structb_tag
{
char c;
int i;
} structb_t;
It actually
typedef struct structb_tag
{
char c;
char[3] unseen_members;
int i;
} structb_t;
Accessing these unseen members will not cause any segmentation fault. In the point of view of OS, there's no difference between accessing members declared by programmers explicitly and declared by compiler implicitly.
#include <stdio.h>
#include <string.h>
typedef struct Test {
char c;
int i;
} MyTest;
int main() {
MyTest my_test;
memset(&my_test, 0, sizeof(my_test));
my_test.c = 1;
int* int_ptr = (int *)&my_test.c;
printf("Size of my_test is %lu\n", sizeof(my_test));
printf("Value of my_test.c(char) is %d\n", my_test.c);
printf("Value of my_test.c(int) is %d\n", *int_ptr);
return 0;
}
This gives:
Size of my_test is 8
Value of my_test.c(char) is 1
Value of my_test.c(int) is 1
We can access any byte in the structure using a pointer to that structure and typecasting that pointer to (char *) if we accordingly increment that pointer then we can access any byte but this not good programming skill. Structures are padded with some extra bytes so that an execution of the program can become faster.
I have a complex structure which looks like this.
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
}x;
struct c
{
int c_inner_int;
char c_inner_char;
}y;
}z;
I use a function, that takes address of "struct c" as an argument. Now I want this function to copy the values of "struct c" to "struct b". The function call that I make in the main function may look like this.
copy_val(&z.y);
Now, how do I define copy_val? Any suggestions?
If i define a pointer of type struct c, like below it isn't working.
void copy_val(struct c *addr)
{
struct c *tmp=addr;
int tmp_int=tmp->c_inner_int;
int tmp_char=tmp->c_inner_char;
tmp=tmp-1; /** assuming that b and c are of same type and decrementing pointer by 1 takes to beginning of b **/
tmp->b_inner_int=tmp_int;
tmp->b_inner_char=tmp_char;
}
#include <stdio.h>
#include <stddef.h>
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
}x;
struct c
{
int c_inner_int;
char c_inner_char;
}y;
}z;
void copy_val(struct c *addr){
size_t offset_c = offsetof(struct a, y);
size_t offset_b = offsetof(struct a, x);
struct b *bp = (struct b*)((char*)addr - offset_c + offset_b);
bp->b_inner_int = addr->c_inner_int;
bp->b_inner_char = addr->c_inner_char;
}
int main(void){
z.y.c_inner_int = 1;
z.y.c_inner_char = '1';
copy_val(&z.y);
printf("%d, %c\n", z.x.b_inner_int, z.x.b_inner_char);
return 0;
}
You say that you want to take the address of a structure member, and reference other members based on that.
That's a bit iffy; the natural thing to do would be to take the address of the top-level structure whose members you want to work with, i.e. a struct a.
Also, it can be simplified:
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
} x, y;
} z;
With that done, you can do just:
z.x = z.y;
to copy the entire value of type struct b.
If you pass like this copy_val(&z.y); you can't catch it in proper way because you have structure inside structure. so try to pass whole structure and copy it-
copy_val(&z);
Try the following code-
void copy_val(struct z *addr)
{
addr->x.b_inner_int= addr->y.c_inner_int;
addr->x.b_inner_char= addr->y.c_inner_char;
}
Your assumption that b and c are the same type is invalid, according to the C standard section 6.2.7 p.1 (emphasis mine):
...if one member of the pair is declared with a name, the other is declared
with the same name.
Because the structs use different member names, they are not considered compatible, thus your assumption is invalid.
Further, even if they are the exact same type, the tmp=tmp-1; statement is not valid: while sizeof(struct b) may report something like 8, this does not mean there's zero padding between the two structures.
Instead, you should use the offsetof macro to get the address of z, given the address of z.y:
struct a *z = (struct a *)((char *)addr - offsetof(struct a, y));
Note, however, that this may break aliasing assumptions, as part of the object pointing to z is also pointed to by y, but the pointers are not compatible.
include <stdio.h>
struct a
{
struct b
{
int b_inner_int;
char b_inner_char;
}x;
struct c
{
int c_inner_int;
char c_inner_char;
}y;
}z;
void copy_val(struct c *c_pointer)
{
struct b *tmp = (struct b *) (c_pointer-1);
tmp->b_inner_int = c_pointer->c_inner_int;
tmp->b_inner_char = c_pointer->c_inner_char;
}
int main(int argc, char **argv)
{
struct a test;
test.y.c_inner_int = 32;
test.y.c_inner_char = 'A';
copy_val(&test.y);
printf("b inner int : %d\n", test.x.b_inner_int);
printf("b inner char %c\n", test.x.b_inner_char);
return 0;
}
I have a structure:
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
char payload[1024];
} bar;
I want to find out, at configure time, if I need to insert padding to make 'payload' double-aligned.
Autoconf provides AC_CHECK_SIZEOF(type) and AC_CHECK_ALIGNOF(type), but what I really need is something like AC_CHECK_OFFSETOF(type, member). If the reported offset was not double-aligned, I could introduce enough padding to make it so.
I could run a little test program that reported offsetof(struct bar, payload), but I don't want to introduce a run-time check into my build system (we cross-compile not infrequently).
Using a zero length bitfield might solve this problem without autotool tricks.
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
int64_t : 0; // or long long whatever integer type is sizeof(double)
char payload[1024];
} bar;
You can use AC_COMPUTE_INT:
AC_COMPUTE_INT([payload_offset], [offsetof(struct bar, payload)], ...)
But it would probably be easier just to use an anonymous union to force alignment:
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
union {
char payload[1024];
double dummy; /* for alignment */
};
} bar;
If you don't want to use a union, you can compute the padding in place:
struct foo {
struct header {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
char padding[(alignof(double) - 1) - ((sizeof(struct header)
+ alignof(double) - 1) % alignof(double))];
char payload[1024];
} bar;
I don't really think that autoconf can tell you that, as it is a matter of the compiler who decides to add padding or not. So I would think that the only reasonable way would be to compile a program that checks if offset of the member equals to what you think it should be equal.
I am attempting to learn more about C and its arcane hidden powers, and I attempted to make a sample struct containing a pointer to a void, intended to use as array.
EDIT: Important note: This is for raw C code.
Let's say I have this struct.
typedef struct mystruct {
unsigned char foo;
unsigned int max;
enum data_t type;
void* data;
} mystruct;
I want data to hold max of either unsigned chars, unsigned short ints, and unsigned long ints, the data_t enum contains
values for those 3 cases.
enum Grid_t {gi8, gi16, gi32}; //For 8, 16 and 32 bit uints.
Then I have this function that initializes and allocates one of this structs, and is supposed to return a pointer to the new struct.
mystruct* new(unsigned char foo, unsigned int bar, long value) {
mystruct* new;
new = malloc(sizeof(mystruct)); //Allocate space for the struct.
assert(new != NULL);
new->foo = foo;
new->max = bar;
int i;
switch(type){
case gi8: default:
new->data = (unsigned char *)calloc(new->max, sizeof(unsigned char));
assert(new->data != NULL);
for(i = 0; i < new->max; i++){
*((unsigned char*)new->data + i) = (unsigned char)value;
//Can I do anything with the format new->data[n]? I can't seem
//to use the [] shortcut to point to members in this case!
}
break;
}
return new;
}
The compiler returns no warnings, but I am not too sure about this method. Is it a legitimate way to use pointers?
Is there a better way©?
I missed calling it. like mystruct* P; P = new(0,50,1024);
Unions are interesting but not what I wanted. Since I will have to approach every specific case individually anyway, casting seems as good as an union. I specifically wanted to have much larger 8-bit arrays than 32-bits arrays, so an union doesn't seem to help. For that I'd make it just an array of longs :P
No, you cannot dereference a void* pointer, it is forbidden by the C language standard. You have to cast it to a concrete pointer type before doing so.
As an alternative, depending on your needs, you can also use a union in your structure instead of a void*:
typedef struct mystruct {
unsigned char foo;
unsigned int max;
enum data_t type;
union {
unsigned char *uc;
unsigned short *us;
unsigned int *ui;
} data;
} mystruct;
At any given time, only one of data.uc, data.us, or data.ui is valid, as they all occupy the same space in memory. Then, you can use the appropriate member to get at your data array without having to cast from void*.
What about
typedef struct mystruct
{
unsigned char foo;
unsigned int max;
enum data_t type;
union
{
unsigned char *chars;
unsigned short *shortints;
unsigned long *longints;
};
} mystruct;
That way, there is no need to cast at all. Just use data_t to determine which of the pointers you want to access.
Is type supposed to be an argument to the function? (Don't name this function or any variable new or any C++ programmer who tries to use it will hunt you down)
If you want to use array indices, you can use a temporary pointer like this:
unsigned char *cdata = (unsigned char *)new->data;
cdata[i] = value;
I don't really see a problem with your approach. If you expect a particular size (which I think you do given the name gi8 etc.) I would suggest including stdint.h and using the typedefs uint8_t, uint16_t, and uint32_t.
A pointer is merely an address in the memory space. You can choose to interpret it however you wish. Review union for more information on how you can interpret the same memory location in multiple ways.
casting between pointer types is common in C and C++, and the use of void* implies that you dont want users to accidentally dereference (dereferencing a void* will cause an error, but dereferencing the same pointer when cast to int* will not)
typedef struct {
unsigned char a,
unsigned char b,
unsigned char c
}type_a;
typedef struct {
unsigned char e,
unsigned char f[2]
}type_b;
type_a sample;
sample.a = 1;
sample.b = 2;
sample.c = 3;
How do I typecast it and assign new value like:
sample = (type_b)sample; // syntax error
sample.f[1] = 'a';
You should really try it out yourself.
sample = (type_b)sample; /* Can't cast a structure to
another structure. */
sample.f[1] = 'a'; /* sample is still of type type_a,
and doesn't have an `f` field. */
No - C types are static, which means that sample will always remain of type type_a. However, you can achieve what you want using unions:
union {
type_a as_a;
type_b as_b;
} sample;
sample.as_a.a = 1;
sample.as_a.b = 2;
sample.as_a.c = 3;
sample.as_b.f[1] = 'a';
Note that it is not usual to create an object that is a bare union type like this; normally you would include the union within a struct, that includes a tag so that you know what type the object is at the present time:
struct {
enum { TYPE_A, TYPE_B } type;
union {
type_a as_a;
type_b as_b;
} data;
} sample;
/* sample is a TYPE_A right now */
sample.type = TYPE_A;
sample.data.as_a.a = 1;
sample.data.as_a.b = 2;
sample.data.as_a.c = 3;
/* sample is now a TYPE_B */
sample.type = TYPE_B;
sample.data.as_b.f[1] = 'a';
You can't cast one data type to another incompatible data type. However, the memory is open for you. You can access it as follows:
typedef struct
{
unsigned char a;
unsigned char b;
unsigned char c;
}type_a;
typedef struct
{
unsigned char e;
unsigned char f[2];
}type_b;
type_a sample;
sample.a = 1;
sample.b = 2;
sample.c = 3;
type_b *sample_b = (type_b *) ((void*) &sample);
Try out yourself accessing sample_b->e and sample_b->f and see what happens.
No. You can do it by casting pointers: value_b = *((value_b*)&value_a) or by creating union of those two types.
However you do it, be careful. Structures can have different data alignment and you may get unexpected results.
yes you can copy the value of the type_a into type_b by trying something like
type_b sample_b =*((type_b*)&sample);
or
memcpy(&sample_b,&sample,sizeof(type_a));
Typecasting is nothing but converting an expression of one type to another one. But you seem to be trying to convert the type itself, which is fixed at compile time(variable declaration)
Its not clear the idea behind trying something like this. If you can make it more clear, people would be able to give more insights