Is there any alignment requirement in C99 standard for basic object ?
to say, requires an int object to be aligned by sizeof(int) bytes ?
The alignment of any character type is 1.
The following macro is an example of what Mr. E. Sosman mentioned
else-thread. It is derived from a macro by Mr. Chris M. Thomasson.
#include <stddef.h>
#define AlignOf(type_) (offsetof(struct { char c; type_ t; }, t))
Note that this macro has some light challenges:
- The 'type_' argument must be a simple type-name, suitable for the
'struct' member definition 'type_ t'. For example 'char (*)[10]' is not
such a simple type; you can't have 'char (*)[10] t'.
- Some compilers warn about tagless 'struct' definitions.
- The following equality is not guaranteed for any type 'typename':
'AlignOf(typename) == AlignOf(typename)', since after expansion, there
are two distinct 'struct' types that are not the same type. It's
probably pretty unlikely that a compiler will cause this problem. If
you trust that the alignment will not exceed the range of values for an
'int', you can use:
enum { AlignOfFoo = AlignOf(Foo) };
to ensure that you have an 'AlignOfFoo' value that is an integer
constant expression. That's kind of ugly, but oh well.
As far as I know, in C11, an alignment value must be a power of two.
That makes it pretty unlikely that there was any non-power-of-two
alignment for any pre-C11 implementation. Believing that, if you find
the integer factors for 'sizeof (type)' and the only factors are '1' and
'sizeof (type)', then the alignment requirement must be one or the
other. If you only have these two choices, and if 'sizeof (type) &
(sizeof (type) - 1)' is non-zero, then 'sizeof (type)' is not a power of
two and you're pretty safe believing the alignment requirement is thus '1'.
I believe a portable alignment strategy for pre-C99 where one wishes to
have a variably-sized array following some fixed-sized header is to do
something like:
#include <stddef.h>
#include <stdlib.h>
/* Object types */
typedef int elementtype;
struct s_counted_array;
struct s_aligned_counted_array;
/* Function declarations */
static void * new_counted_array(size_t);
/* Struct/union definitions */
struct s_counted_array {
size_t count;
elementtype * array;
};
/* Function definitions */
int main(void) {
struct s_counted_array * my_array;
/* Allocate a counted array with 42 elements */
my_array = new_counted_array(42);
if (!my_array) {
/* Allocation failed */
return EXIT_FAILURE;
}
/*
* Use the counted array. Assign to
* the last element, for example
*/
my_array->array[my_array->count - 1] = 13;
/* Deallocate the whole thing */
free(my_array);
return EXIT_SUCCESS;
}
static void * new_counted_array(size_t count) {
struct s_aligned_counted_array {
struct s_counted_array header[1];
elementtype a[1];
};
register const size_t offset =
offsetof(struct s_aligned_counted_array, a);
void * memory;
struct s_counted_array * obj;
if (!count) {
/* Don't allocate for 0 elements */
return NULL;
}
obj = memory = malloc(offset + count * sizeof obj->array[0]);
if (memory) {
/*
* Allocation succeeded. Point
* the 'array' member to the array
*/
obj->array = (void *) ((char *) memory + offset);
/* And note the count of elements */
obj->count = count;
}
return obj;
}