I can use pragma pack on various compilers to force structs to have fields which are not on their natural alignments.
Is this recursive - so suppose struct typedef A contains a field of typedef struct B. If use a pragma to pack A will this force struct B to be packed?
You have to hope not! Lets say you have a function that takes a parameter struct A:
void fn( struct A x ) ;
and then a packed struct B that has struct A as a member:
#pragma pack(1)
struct B
{
struct A a ;
}
If you pass the member a of B to fn(), the function has no knowledge of the packing in this instance, and would fail.
Other answerer's results notwithstanding, I performed the following test on VC++ 2010:
struct A
{
int a;
char b;
int c ;
} ;
struct B
{
struct A d ;
} ;
#pragma pack(1)
struct C
{
struct A d ;
} ;
#pragma pack(1)
struct D
{
int a;
char b;
int c ;
} ;
#pragma pack(1)
struct E
{
struct D ;
} ;
int main()
{
int a = sizeof(struct A) ;
int b = sizeof(struct B) ;
int c = sizeof(struct C) ;
int d = sizeof(struct D) ;
int e = sizeof(struct E) ;
}
Inspection of a, b, c, d and e in main() in the debugger yield:
a = 12
b = 12
c = 12
d = 9
e = 9
The packing of struct C has no effect on the size of its struct A member.
Just don't. The exact behavior of an ugly nonstandard extension is not something you can even ask questions about without specifying an exact platform/compiler you're working with. If you find yourself needing packed structs, you'd be better to figure out why your code is broken and fix it. Packed structs are a band-aid for broken code that do nothing to fix the root cause of the brokenness.
Folowing Nathon's post, I tried about the same thing on my computer:
#include <stdio.h>
#if defined PACK_FIRST || defined PACK_BOTH
#pragma pack(1)
#endif
struct inner {
char a;
double b;
};
#if defined PACK_SECOND || defined PACK_BOTH
#pragma pack(1)
#endif
struct outer {
char a;
struct inner b;
char c;
double d;
};
int main(void) {
printf("sizeof (char): %d (1, of course)\n", (int)sizeof (char));
printf("sizeof (double): %d\n", (int)sizeof (double));
printf("sizeof (inner): %d\n", (int)sizeof (struct inner));
printf("sizeof (outer): %d\n", (int)sizeof (struct outer));
return 0;
}
$ gcc 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 16
sizeof (outer): 40
$ gcc -DPACK_FIRST 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 9
sizeof (outer): 19
$ gcc -DPACK_SECOND 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 16
sizeof (outer): 26
$ gcc -DPACK_BOTH 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 9
sizeof (outer): 19
Apparently my gcc packs from the point where the #pragma line appears.
For the version of GCC I have handy, it looks like yes:
#include <stdio.h>
typedef struct
{
char a;
int b;
}inner_t;
#pragma pack(1)
typedef struct
{
char a;
inner_t inner;
} outer_t;
int main()
{
outer_t outer;
outer.inner.a = 'a';
outer.inner.b = 0xABCDEF01;
printf ("outer.inner.a: %c\n", outer.inner.a);
return 0;
}
And gdb breaking on the printf gives me...
(gdb) x/5xw &outer
0x7fffffffe4b0: 0xffff61a0 0xcdef01ff 0x000000ab 0x00000000
0x7fffffffe4c0: 0x00000000
inner.b is not word aligned. So under GCC 4.4.5 on a little endian 64-bit machine, nested structures are packed if the outer structure is packed. Pardon my typedefs, those of you who don't like them.
Related
I have many programs where structs are defined. And each time, I have to create a function to print the members. For example,
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
void printMyStruct(myStruct myPeople) {
printf("%s\n",myPeople.name);
printf("%s\n",myPeople.address);
printf("%d\n",myPeople.zip);
}
int main()
{
myStruct myPeople={"myName" , "10 myStreet", 11111};
printMyStruct(myPeople);
}
I know that reflection is not supported in C. And so, I write these printing functions for each struct I defined.
But, I wonder if it exists any tricks to generate automatically these printing functions. I would understand that I have to modify a little bit these functions. But, if a part of the job is done automatically, it would be great.
(This example is simple, sometimes struct are nested or I have array of structs or some fields are pointers, ...)
You can of-course print structs, but expect a lot of non-readable output:
#include <stdio.h>
#include <ctype.h>
struct example {
int x;
int y;
char c;
};
#define NOT_PRINTABLE "Not Printable"
void print_structure(const char *structure, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%ld)\t%.2X: %.*s\n", i, structure[i],
(isprint(structure[i]) ? 1 : sizeof(NOT_PRINTABLE) - 1),
(isprint(structure[i]) ? &structure[i] : NOT_PRINTABLE));
}
}
int main(int argc, char **argv) {
struct example a;
a.x = 5;
a.y = 6;
a.c = 'A';
print_structure((char *)&a, sizeof(struct example));
return 0;
}
But the issue is that, it will print the structs as it is represented in memory. So 4 byte (32 bit) integer 1 will be represented with 4 bytes, not the char '1'.
And due to the way pointers work, you cannot make out if a member is a pointer or a non-pointer.
Another issue is that structures have padding to help with alignment, and better/efficent use of memory. So you would see a lot of 0x00 in the middle.
Remember that C is a compiled language.
let's consider to use https://copilot.github.com/. it's great.
this is what i have with copilot
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
//print struct myStruct >> auto generate by codepilot after you type a comment `print struct myStruct`
void printStruct(myStruct *s) {
printf("name: %s\n", s->name);
printf("address: %s\n", s->address);
printf("zip: %d\n", s->zip);
}
I have a simple C program of below type
#include<stdio.h>
struct test{
char a;
char b;
char c;
char d;
int e;
};
void main() {
struct test mem = {0xa, 0xb, 0xc, 0xd, 0xef12};
long int *tmp = (long int *)(&mem.a);
printf("Struct in binary %p : 0x%lx\n", &mem.a, *tmp);
printf("Printing only a member %p : 0x%x\n", &(mem.e), *(int *)(&(mem.e)));
}
The output of above program is as below on a Big endian machine :
Struct in binary 0x7ffc1206abc0 : 0xef120d0c0b0a
Printing only a member 0x7ffc1206abc4 : 0xef12
The question is that why is the raw output of the struct in the reverse order of its members' values?
The address of 'member e' is still 4 bytes from the start of the struct base address..!
Please consider this sample go code:
package main
//#include <stdio.h>
//#include <stdint.h>
//#pragma pack(push, 1)
//struct Packed_Struct {
// uint16_t A;
// uint16_t B;
// uint32_t C;
// uint16_t D;
//};
//#pragma pack(pop)
//
//struct UnPacked_Struct {
// uint16_t A;
// uint16_t B;
// uint32_t C;
// uint16_t D;
//};
//
//
//void print_C_struct_size(){
// struct Packed_Struct Packed_Struct;
// struct UnPacked_Struct UnPacked_Struct;
// printf("Sizeof Packed_Struct: %lu\n", sizeof(Packed_Struct) );
// printf("Sizeof UnPacked_Struct: %lu\n", sizeof(UnPacked_Struct) );
// return;
//}
//
import "C"
import(
"fmt"
"unsafe"
)
type GoStruct struct{
A uint16
B uint16
C uint32
D uint16
}
func main(){
fmt.Println("Hello world!")
meh := C.print_C_struct_size()
var GoStruct GoStruct
fmt.Printf("Sizeof GoStruct : %d\n", unsafe.Sizeof(GoStruct) )
fmt.Printf("meh type: %T\n", meh)
}
The output is:
$ go run cgo.go
Hello world!
Sizeof Packed_Struct: 10
Sizeof UnPacked_Struct: 12
Sizeof GoStruct : 12
meh type: main._Ctype_void
Notice that the struct when packed takes 10 bytes, 12 otherwise. By default, my tries in Go seems to take 12 bytes as shown here.
Is there a Go-ish way to pack this struct so it uses only 10 bytes?
So, per https://github.com/golang/go/wiki/cgo#struct-alignment-issues:
Go doesn't support packed struct (e.g., structs where maximum alignment is 1 byte), you can't use packed C struct in Go. Even if your program passes compilation, it won't do what you want. To use it, you have to read/write the struct as byte array/slice.
From "what" I understood, I've put together this: https://play.golang.org/p/OmdMVDMikSn.
Essentially, set up the struct, and binary.Write it into a byte slice, the slice shows 10 bytes.
I am trying to do packed struct in tcc C compiller.
Code is as follows and __attribute __ tag should be supported:
#include <stdio.h>
#include <stdint.h>
typedef struct _test_t{
char c;
uint16_t i;
char d;
} __attribute__((__packed__)) test_t;
int main(){
test_t x;
x.c = 0xCC;
x.i = 0xAABB;
x.d = 0xDD;
const char *s = (const char *) & x;
unsigned i;
for(i = 0; i < sizeof(x); i++)
printf("%3u %x\n", i, 0xFF & s[i]);
return 0;
}
It works in gcc, but not work on tcc.
I also tried __attribute __((packed)) and few other tests - none works.
As you already found the __attribute__ extension applies only to struct's members, so each of them should have it applied individually. Here is your code with minor adaptations, that compiles with tcc 0.9.26 and then runs with correct output:
typedef struct {
char c __attribute__((packed));
unsigned short i __attribute__((packed));
char d __attribute__((packed));
} test_t;
int main(void)
{
test_t x;
printf("%zu\n", sizeof(test_t));
x.c = 0xCC;
x.i = 0xAABB;
x.d = 0xDD;
const char *s = (const char *) &x;
unsigned i;
for (i = 0; i < sizeof(x); i++)
printf("%3u %x\n", i, 0xFF & s[i]);
return 0;
}
Result:
4
0 cc
1 bb
2 aa
3 dd
There is one catch here. As you may already spotted there are no headers. The correctly written code should have:
#include <stdio.h>
#include <stdint.h> // then replace unsigned short with uint16_t
However, with headers the __attribute__ is no longer working. I am not sure if that always happen, but on my system (CentOS 6) it does exactly in that way.
As I found the explanation lies in internal sys/cdefs.h header, that contains:
/* GCC has various useful declarations that can be made with the
`__attribute__' syntax. All of the ways we use this do fine if
they are omitted for compilers that don't understand it. */
#if !defined __GNUC__ || __GNUC__ < 2
# define __attribute__(xyz) /* Ignore */
#endif
so the __attribute__ function-like macro is "washed-up" for tcc, as it does not define __GNUC__ macro. It seems to be some incoherence between tcc developers and standard library (here glibc) writers.
I can confirm that at least with tcc 0.9.26 attribute((packed)) on
struct members is not working. Using Windows-style packing pragmas works just fine:
#if defined(__TINYC__)
#pragma pack(1)
#endif
typedef struct {
uint16_t ..
} interrupt_gate_descriptor_t;
#if defined(__TINYC__)
#pragma pack(1)
#endif
Seems to be error with TCC.
according many sources , including this one, http://wiki.osdev.org/TCC
this should work:
struct some_struct {
unsigned char a __attribute__((packed));
unsigned char b __attribute__((packed));
} __attribute__((packed));
... but it does not work.
struct a
{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
Can anybody explain me how to find the offset of int k so that we can find the address of int i?
Use offsetof() to find the offset from the start of z or from the start of x.
offsetof() - offset of a structure member
SYNOPSIS
#include <stddef.h>
size_t offsetof(type, member);
offsetof() returns the offset of the field member from the
start of the structure type.
EXAMPLE
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */
printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));
exit(EXIT_SUCCESS);
}
You will get the following output on a Linux, if you compile with GCC:
offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16
It's been 3 years since the question has been asked, I'm adding my answer for the sake of completeness.
The hacky way of getting the offset of a struct member goes like this
printf("%p\n", (void*)(&((struct s *)NULL)->i));
It doesn't look pretty, I can't think of anything in pure C (which can get you the offset of the member, without knowing anything else about the structure. I believe the offsetof macro is defined in this fashion.
For reference, this technique is used in the linux kernel, check out the container_of macro :
http://lxr.free-electrons.com/source/scripts/kconfig/list.h#L18
A more elaborate explanation can be found in this article:
http://radek.io/2012/11/10/magical-container_of-macro/
struct a foo;
printf("offset of k is %d\n", (char *)&foo.y.k - (char *)&foo);
printf("offset of i is %d\n", (char *)&foo.x.i - (char *)&foo);
foo.x.i refers to the field i in the struct x in the struct foo.
&foo.x.i gives you the address of the field foo.x.i.
Similarly, &foo.y.k gives you the address of foo.y.k;
&foo gives you the address of the struct foo.
Subtracting the address of foo from the address of foo.x.i gives you the offset from foo to foo.x.i.
As Gangadhar says, you can use the offsetof() macro rather than the pointer arithmetic I gave. But it's good to understand the pointer arithmetic first.
As already suggested, you should use the offsetof() macro from <stddef.h>, which yields the offset as a size_t value.
For example:
#include <stddef.h>
#include <stdio.h>
#include "struct_a.h" /* Header defining the structure in the question */
int main(void)
{
size_t off_k_y = offsetof(struct c, k);
size_t off_k_z = offsetof(struct a, y.k);
size_t off_i_x = offsetof(struct b, i);
size_t off_i_z = offsetof(struct a, x.i);
printf("k = %zu %zu; i = %zu %zu\n", off_k_y, off_k_z, off_i_x, off_i_z);
return 0;
}
Example output:
k = 0 8; i = 0 0
To find the offset, this is one way we can go about it.
struct a{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
int main(){
struct a* foo = &z;
printf("%d\n", foo); //address of z
printf("%d\n", &(foo->y)); //address of z.y
printf("%d\n", &( (&(foo->y))->k )); //address of z.y.k
int offset_k = (char*)&( (&(foo->y))->k ) - (char*)foo ;
printf("%d\n", offset_k);
return 0;
}
Output would be similar to this:
4225552 //address of z
4225560 //address of z.y
4225560 //address of z.y.k
8 //offset
In this particular case, since int i is the first member of the struct, the base address of the struct will be that of int i as well. Otherwise, you could compute the offset of int i in a similar manner.
int offset_i = (char*)&( (&(foo->x))->i ) - (char*)foo; //0 in this case
NOTE: The offset will be negative or positive depending on how you define it (if it's with respect to base address or member z.y.k). Here, it is defined to be with respect to base address of struct.
Here's a generic solution that works with both newer and older versions of GNU C:
<!-- language: C -->
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define GNUC_PREREQ(minMajor, minMinor) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((minMajor) << 16) + (minMinor))
#else
# define GNUC_PREREQ 0
#endif
#if GNUC_PREREQ(4, 0)
# define OFFSETOF(type, member) ((int)__builtin_offsetof(type, member))
#else
# define OFFSETOF(type, member) ((int)(intptr_t)&(((type *)(void*)0)->member) )
#endif
UPDATE: Someone asked for a usage example:
struct foo {
int bar;
char *baz;
}
printf("Offset of baz in struct foo = %d\n",
OFFSETOF(foo, baz));
Would print 4, if int compiles into 4 bytes on the architecture of the machine it runs on.