golang: pack a struct - c

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.

Related

Setting array data in a struct

If when passing to functions we treat parameters uint32_t data[] and uint32_t* data as both being pointers to an array of data, why is the same not true when setting a member of a struct? Quick example:
#include <stdint.h> /* uint32_t */
#include <string.h> /* memcpy */
#include <stdlib.h> /* malloc */
typedef struct {
uint32_t data[1024];
} tData;
typedef struct {
uint32_t *data;
} pData;
int main()
{
// structs
pData pdata;
tData sdata;
// Test 1.
///////////////////////////////////
uint32_t mydata[1024];
// This is OK
pdata.data = mydata;
// This is not OK
sdata.data = mydata;
// But this is OK
memcpy(sdata.data, mydata, 1024);
// Test 2.
///////////////////////////////////
uint32_t *otherdata = malloc(sizeof(uint32_t)*1024);
// This is OK
pdata.data = otherdata;
// This is not OK
sdata.data = otherdata;
// But this is OK
memcpy(sdata.data, otherdata, 1024);
}
In order to satisfy the struct tData must I do a memcpy? Is this the only way?
It looks like an attempt to assign an array directly, something like this (without structs)
int A[10];
int B[10];
int *ptr;
ptr = A; // OK
A = B; // Not ok
assigning array to pointer will make the pointer to point to the first element of the array, while comparing 2 arrays directly is not allowed.
The example with memcpy is equal to copying elements(their memory) one by one. so you can also do something like this.
for(int i = 0; i < 1024; ++i)
sdata.data[i] = mydata[i];

c program how to print a char array held by a structure variable?

How do I print the char array held in the struct variable char binary_filename?
I tried:
printf("Binary file name is : %s \n", prv_instance_t.binary_filename);
However, I get the error error: expected expression before ‘prv_instance_t’
Here is the struct definition.
#define BINARY_FILE_NAME_MAXLEN 10
typedef struct _prv_instance_
{
/*
* The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest
* is the instance scope user data (uint8_t power in this case)
*/
struct _prv_instance_ * next; // matches lwm2m_list_t::next
uint16_t shortID; // matches lwm2m_list_t::id
uint8_t power;
uint8_t reset;
double dec;
char binary_filename[BINARY_FILE_NAME_MAXLEN];
} prv_instance_t;
You are using the type itself. To access a member of the struct you have to declare an instance of that struct first. For example, this will print Hello World :
#include <stdio.h>
#include <string.h>
#define BINARY_FILE_NAME_MAXLEN 10
typedef struct _prv_instance_
{
char binary_filename [BINARY_FILE_NAME_MAXLEN];
} prv_instance_t;
int main()
{
prv_instance_t foo, bar;
strcpy(foo.binary_filename, "Hello");
strcpy(bar.binary_filename, "World");
printf("%s %s\n", foo.binary_filename, bar.binary_filename);
return 0;
}
What you are trying to do is similar to
printf("%d", int);
Just remove typedef keyword.
Current definition does not define a variable, but makes two equivalent types prv_instance_t and struct _prv_instance_. From your question I understand that prv_instance_t should be an instance (variable) of type _prv_instance_, keyword typedef is unnecessary.
Your printf will work with:
#define BINARY_FILE_NAME_MAXLEN 10
struct _prv_instance_
{
/*
* The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest
* is the instance scope user data (uint8_t power in this case)
*/
struct _prv_instance_ * next; // matches lwm2m_list_t::next
uint16_t shortID; // matches lwm2m_list_t::id
uint8_t power;
uint8_t reset;
double dec;
char binary_filename[BINARY_FILE_NAME_MAXLEN];
} prv_instance_t;
as well as with the following one:
#define BINARY_FILE_NAME_MAXLEN 10
struct _prv_instance_
{
/*
* The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest
* is the instance scope user data (uint8_t power in this case)
*/
struct _prv_instance_ * next; // matches lwm2m_list_t::next
uint16_t shortID; // matches lwm2m_list_t::id
uint8_t power;
uint8_t reset;
double dec;
char binary_filename[BINARY_FILE_NAME_MAXLEN];
};
struct _prv_instance_ prv_instance_t;

Best way to declare specific width variables depending on user input

I have a code which looks as shown below. The code here is if the word_size = 64. In similar fashion I need to have for 32 and 16 too. I can't find a way to reuse the same encrypt function for all the sizes. Moreover, I need to declare the variables too according to the word_size, ie. to use either uint_16 or uint_32 or uint_64 depends upon word_size. Can you help me with writing a reusable code in this case?
#include<stdio.h>
#include<stdint.h>
void encrypt(uint64_t* , uint64_t*, uint64_t*);
int main(){
int block_size;
// Get the user inputs
printf("input the block size: \n");
scanf("%d", &block_size); // can be 32, 64 or 128
int word_size = block_size/2; // 16,32 or 64
// Depending on the word_size, I should declare the variables with
// corresponding width
uint64_t plain_text[2] = {0,0};
uint64_t cipher_text[2] = {0,0};
uint64_t key_text[2] = {0,0};
uint64_t * pt, *ct, *k;
encrypt(pt, ct,k);
}
/*
* Ecnryption Method
*/
void encrypt(uint64_t* pt, uint64_t* ct, uint64_t* k){
// Involves bit shifting algorithm which works only on exact sizes i.e eiter 16,32 or 64.
}
I can provide more information if needed.
There is a way to do this in C - by using struct and union
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
enum type {
U64,
U32,
U16,
U8,
};
struct container {
enum type type;
union {
uint64_t u64;
uint32_t u32;
uint16_t u16;
uint8_t u8;
} value;
};
int test(struct container container) {
switch(container.type) {
case U64:
printf("Value is :%" PRIu64 "\n", container.value);
break;
case U32:
printf("Value is :%" PRIu32 "\n", container.value);
break;
case U16:
printf("Value is :%" PRIu16 "\n", container.value);
break;
case U8:
printf("Value is :%" PRIu8 "\n", container.value);
break;
}
return 0;
}
int main(int argc, char **argv) {
struct container c1, c2;
c1.type = U64;
c1.value.u64 = 10000000000ULL;
c2.type = U8;
c2.value.u8 = 100;
test(c1);
test(c2);
return 0;
}
The output produced was:
Value is :10000000000
Value is :100

How to break struct members into bytes of a single word

Say I have a C structure like:
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData; } tempStruct;
Is there a way to put all of those 3 members of the struct into a single 32-bit word, yet still be able to access them individually?
Something with the help of unions?
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData;
}
tempStruct;
typedef union {
tempStruct myStruct;
UINT32 myWord;
} stuff;
Or even better (with no "intermediate" struct):
#include <stdlib.h>
#include <stdio.h>
typedef union {
struct {
int nRow:8;
int nCol:8;
int nData:16;
};
int myWord;
} stuff;
int main(int args, char** argv){
stuff a;
a.myWord=0;
a.nCol=2;
printf("%d\n", a.myWord);
return 0;
}
What about just referring to it as a UINT32? It's not like C is type-safe.
tempStruct t;
t.nRow = 0x01;
t.nCol = 0x02;
t.nData = 0x04;
//put a reference to the struct as a pointer to a UINT32
UINT32* word = (UINT32 *) &t;
printf("%x", *word);
You can then get the value of the struct as a 32-bit word by dereferencing the pointer. The specifics of your system may matter, though...if I run this on my machine, the value of word is 0x00040201---that is, the fields are in reverse order. I don't think that's necessarily going to be the case if you're trying to serialize this to another system, so it's not portable.
If you want to actually store it as a 32-bit integer and then refer to the fields individually, why not
UINT32 word = 0x01020004;
and then somewhere else...
UINT8* row(UINT32 word) {
return (UINT8 *) &word + 3;
}
UINT8* col(UINT32 word) {
return ((UINT8 *) &word) + 2;
}
UINT16* data(UINT32 word) {
return ((UINT16 *) &word);
}
Macros will facilitate portable endianness.
Yes, you can use bit fields in C to do that. Something like:
typedef struct {
unsigned nRow : 8;
unsigned nCol : 8;
unsigned nData : 16;
} tempStruct;
If you want to control the memory layout also, you might want to take a look at #pragma pack. A non-portable option available on some compilers for this.
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
nRow will take only 8 bit and nCol will take 8 bit and nDate will take 16bit.
This will work for you.
I just wrote sample program to see the size of it
#include<stdio.h>
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
typedef struct {
int nRow;
int nCol;
int nData; } tempStructZ;
int main(void) {
printf("%d\n", sizeof(tempStruct));
printf("%d\n", sizeof(tempStructZ));
return 0;
}
Output:
4
16

C struct padding

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.

Resources