Re: alignment/zero length arrays



On 25 Aug 2006 11:28:07 -0700, "Bill Pursell" <bill.pursell@xxxxxxxxx>
wrote:

I have a program that does most of its work traversing
a bunch of lists. The lists contain a void *, and I spent
some time today replacing the void *'s with a copy
of the data at the end of the structure as a zero length
array. The performance improvement that resulted by
avoiding the need to dereference the ptr was substantial,
but it has left me with an uncertain feeling. In particular,
changing an assignment caused the output to change,
and I'm not happy about it. The change that I think
should not have any affect is:

We would have to see your real code to discuss this. For example, do
you reuse the struct?


struct foo *f;
f = (struct foo *)&list_element->zdata;

This sets pointer f to point to the data in your element.


becomes

struct foo f;
f = *(struct foo *)&list_element->zdata;

This copies the data from your element to the structure f.


This is better described with the full program below.
My question is: 1) Are the final 3 assignments in this program
reliable?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct foo {
int x,y,z;
};


struct list_el {
void *data;
/* other stuff that throws off alignment */
/* gnu extension...*/
char zdata[] __attribute__((aligned(8)));

The first part of this is a syntax error. (You could achieve the
intended result with [1].) The second part is non-standard. It also
begs the question how do you know 8 is the proper alignment.

};

extern void * xmalloc(size_t s);

int
main(void)
{
struct list_el *L;
struct foo orig = {0,1,2};
struct foo *copy_ptr;
struct foo copy;

L = xmalloc(sizeof *L + sizeof orig);

You don't provide xmalloc but I will assume it does the obvious.

L->data = &orig;
memcpy(&L->zdata, &orig, sizeof orig);

copy_ptr = (struct foo *)L->data;

The cast is superfluous. data is a void* which can be implicitly
converted to any other object pointer type.

In answer to your question, data contains the address of a struct foo.
copy_ptr is a pointer to struct foo. It is reliable to assign such an
address to such a pointer. The conversion to void* (three statements
prior) and from void* (here) are well defined.


copy_ptr = (struct foo *)&L->zdata;

This is "reliable" only if zdata is properly aligned to a struct foo.


copy = *(struct foo*)&L->zdata;

This also is "reliable" only if zdata is properly aligned.


return EXIT_SUCCESS;
}


Remove del for email
.



Relevant Pages

  • Re: I cannot see the need for auto_ptr?!
    ... >object without using a pointer at all? ... >void f ... an exception safe way. ...
    (comp.lang.cpp)
  • Re: alignment/zero length arrays
    ... The lists contain a void *, ... you reuse the struct? ... struct foo *f; ...
    (comp.lang.c)
  • Re: Function pointer to void function and int function
    ... struct foo f; ... ... If you call such a function through a `)' pointer, the compiler will not know it's supposed to generate the hidden `_value_ptr' argument nor the hidden `_returned_struct' object it should point to. ... that calls a function returning `int' and ignores the returned ... value is identical to the machinery that calls a `void' function. ...
    (comp.lang.c)
  • Re: FAQ 4.9 and void**
    ... > pointer to a function by reference". ... You can use void ** to pass a void * ... pass an int *, or a struct foo *, or a FILE *, for initialization ...
    (comp.lang.c)
  • alignment/zero length arrays
    ... The lists contain a void *, ... struct foo *f; ... int x,y,z; ...
    (comp.lang.c)