Skip to content

Instantly share code, notes, and snippets.

@BugsBeGone
Created April 1, 2019 10:46
Show Gist options
  • Save BugsBeGone/8bf86685b532492f877a4ed5db7ce128 to your computer and use it in GitHub Desktop.
Save BugsBeGone/8bf86685b532492f877a4ed5db7ce128 to your computer and use it in GitHub Desktop.
x86 Android native structure tests (for Java Native Access: https://github.com/java-native-access/jna/issues/1079)
/* x86 linux (including Android) structure alignment test for JNA */
#include <assert.h> /* static_assert() */
#include <stddef.h> /* offsetof() */
/* My own simple test struct example: a 4-byte float and an 8-byte double.
* With a maximum alignment of 4 bytes, it should not require any padding and
* should always take up just 12 bytes, regardless of the order of members.
*/
typedef struct BugsBeGoneTestStructure {
float field1; /* offset: 0, size: 4, padding: 0 */
double field2; /* offset: 4, size: 8, padding: 0 */
} bbgts; /* Total size: 12 bytes */
bbgts myts; /* Need an instance so we can use sizeof */
/* Test offsets */
static_assert(offsetof(bbgts, field1) == 0, "offsetof float (myts.field1) != 0");
static_assert(offsetof(bbgts, field2) == 4, "offsetof double (myts.field2) != 4");
/* Test sizes */
static_assert(sizeof(myts.field1) == 4, "sizeof float (myts.field1) != 4");
static_assert(sizeof(myts.field2) == 8, "sizeof double (myts.field2) != 8");
/* Test total size */
static_assert(sizeof(myts) == 12, "sizeof struct myts != 12");
/* Test padding */
static_assert((offsetof(bbgts, field2) - offsetof(bbgts, field1) - sizeof(myts.field1)) == 0, "padding for myts.field1 != 0");
static_assert((sizeof(myts) - offsetof(bbgts, field2) - sizeof(myts.field2)) == 0, "padding for myts.field2 != 0");
int main(void) {
return 0;
}
/* x86 linux (including Android) structure alignment test for JNA */
#include <assert.h> /* static_assert() */
#include <stddef.h> /* offsetof() */
/* This is the C equivalent of the definition for TestStructure, from method
* testGNUCAlignment() in master/test/com/sun/jna/StructureTest.java, line 170+.
*/
typedef struct JNATestStructure {
char b; /* offset: 0, size: 1, padding: 1 */
short s; /* offset: 2, size: 2, padding: 0 */
int i; /* offset: 4, size: 4, padding: 0 */
long l; /* offset: 8, size: 4, padding: 0 */
float f; /* offset: 12, size: 4, padding: 0 */
double d; /* offset: 16, size: 8, padding: 0 */
} jnats; /* Total size: 24 bytes */
jnats ts; /* Need an instance so we can use sizeof */
/* According to the JNA source, the expected size of the struct is 28 or 32:
* "final int SIZE = Native.MAX_ALIGNMENT == 8 ? 32 : 28;"
* With NDK r17c (the last revision before gcc was removed), I get neither of
* these sizes compiling with i686-linux-android-gcc. Likewise with NDK r19c,
* I still get neither of these sizes compiling with i686-linux-android16-clang.
* In fact, no matter what NDK cross compiler I use to target x86, I always get
* the sizes and offsets in the below asserts, which all pass.
*/
/* Test offsets */
static_assert(offsetof(jnats, b) == 0, "offsetof char (ts.b) != 0");
static_assert(offsetof(jnats, s) == 2, "offsetof short (ts.s) != 2");
static_assert(offsetof(jnats, i) == 4, "offsetof int (ts.i) != 4");
static_assert(offsetof(jnats, l) == 8, "offsetof long (ts.l) != 8");
static_assert(offsetof(jnats, f) == 12, "offsetof float (ts.f) != 12");
static_assert(offsetof(jnats, d) == 16, "offsetof double (ts.d) != 16");
/* Test sizes */
static_assert(sizeof(ts.b) == 1, "sizeof char (ts.b) != 1");
static_assert(sizeof(ts.s) == 2, "sizeof short (ts.s) != 2");
static_assert(sizeof(ts.i) == 4, "sizeof int (ts.i) != 4");
static_assert(sizeof(ts.l) == 4, "sizeof long (ts.l) != 4");
static_assert(sizeof(ts.f) == 4, "sizeof float (ts.f) != 4");
static_assert(sizeof(ts.d) == 8, "sizeof double (ts.d) != 8");
/* Test total size */
static_assert(sizeof(ts) == 24, "sizeof struct ts != 24");
/* Test padding */
static_assert((offsetof(jnats, s) - offsetof(jnats, b) - sizeof(ts.b)) == 1, "padding for ts.b != 1");
static_assert((offsetof(jnats, i) - offsetof(jnats, s) - sizeof(ts.s)) == 0, "padding for ts.s != 0");
static_assert((offsetof(jnats, l) - offsetof(jnats, i) - sizeof(ts.i)) == 0, "padding for ts.i != 0");
static_assert((offsetof(jnats, f) - offsetof(jnats, l) - sizeof(ts.l)) == 0, "padding for ts.l != 0");
static_assert((offsetof(jnats, d) - offsetof(jnats, f) - sizeof(ts.f)) == 0, "padding for ts.f != 0");
static_assert((sizeof(ts) - offsetof(jnats, d) - sizeof(ts.d)) == 0, "padding for ts.d != 0");
/* If your compiler passes all of these static asserts with no complaints, that
* must mean that the default maximum alignment for linux x86 really is 4 bytes.
*/
int main(void) {
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment