T
Thomas Troeger
Hello,
I guess everyone is familiar with alignment issues in C. I have run over
a problem where I have two solutions and I would like comments on which
method is better. The problem: Copy (and later access) a structure at an
arbitrary memory location (we can assume there are no size constraints).
The memory could be a database page or something similar.
Here's some example code:
=======================================================================
#include <stdio.h>
#include <string.h>
typedef struct {
int i;
char c;
} foobar_t;
/* align address to be a multiple of n. */
void* align(void* memory, int n)
{
unsigned char* ptr;
unsigned int r;
ptr=(unsigned char*)memory;
r=(unsigned int)ptr%n;
return r ? ptr+n-r: ptr;
}
/* get integer member of foobar_t structure from memory. */
int get_i(void* memory)
{
foobar_t fb;
memcpy(&fb, memory, sizeof(fb));
return fb.i;
}
/* get integer member of aligned foobar_t structure from memory. */
int get_i_aligned(void* memory)
{
return ((foobar_t*)align(memory, sizeof(int)))->i;
}
/* copy foobar to memory location without alignment. */
void store_foobar(void* memory, const foobar_t* fp)
{
memcpy(memory, fp, sizeof(fp));
}
/* copy foobar to memory location with alignment. */
void store_foobar_aligned(void* memory, const foobar_t* fp)
{
store_foobar(align(memory, sizeof(int)), fp);
}
int main(int argc, char* argv[])
{
foobar_t fb={ 42, 'x' };
char buffer[64];
/* unaligned. */
store_foobar(buffer+5, &fb);
printf("%d\n", get_i(buffer+5));
/* aligned. */
store_foobar_aligned(buffer+5, &fb);
printf("%d\n", get_i_aligned(buffer+5));
return 0;
}
=======================================================================
Question #1: Which method is better? memcpy to a stack variable and
accessing members there, or aligning addresses and using direct access?
Question #2: I've scanned through google, Stroustrup and kernel sources
and haven't found an alignment function or macro. How can function
`align()' be implemented better? How can I find a reasonable alignment
boundary for the architecture I'm on (I've cruedly assumend `int')?
Answers and pointers/links to more information would be pretty cool!
Cheers,
Thomas.
I guess everyone is familiar with alignment issues in C. I have run over
a problem where I have two solutions and I would like comments on which
method is better. The problem: Copy (and later access) a structure at an
arbitrary memory location (we can assume there are no size constraints).
The memory could be a database page or something similar.
Here's some example code:
=======================================================================
#include <stdio.h>
#include <string.h>
typedef struct {
int i;
char c;
} foobar_t;
/* align address to be a multiple of n. */
void* align(void* memory, int n)
{
unsigned char* ptr;
unsigned int r;
ptr=(unsigned char*)memory;
r=(unsigned int)ptr%n;
return r ? ptr+n-r: ptr;
}
/* get integer member of foobar_t structure from memory. */
int get_i(void* memory)
{
foobar_t fb;
memcpy(&fb, memory, sizeof(fb));
return fb.i;
}
/* get integer member of aligned foobar_t structure from memory. */
int get_i_aligned(void* memory)
{
return ((foobar_t*)align(memory, sizeof(int)))->i;
}
/* copy foobar to memory location without alignment. */
void store_foobar(void* memory, const foobar_t* fp)
{
memcpy(memory, fp, sizeof(fp));
}
/* copy foobar to memory location with alignment. */
void store_foobar_aligned(void* memory, const foobar_t* fp)
{
store_foobar(align(memory, sizeof(int)), fp);
}
int main(int argc, char* argv[])
{
foobar_t fb={ 42, 'x' };
char buffer[64];
/* unaligned. */
store_foobar(buffer+5, &fb);
printf("%d\n", get_i(buffer+5));
/* aligned. */
store_foobar_aligned(buffer+5, &fb);
printf("%d\n", get_i_aligned(buffer+5));
return 0;
}
=======================================================================
Question #1: Which method is better? memcpy to a stack variable and
accessing members there, or aligning addresses and using direct access?
Question #2: I've scanned through google, Stroustrup and kernel sources
and haven't found an alignment function or macro. How can function
`align()' be implemented better? How can I find a reasonable alignment
boundary for the architecture I'm on (I've cruedly assumend `int')?
Answers and pointers/links to more information would be pretty cool!
Cheers,
Thomas.