On Fri, 04 Jan 2008 18:50:05 +0100, Francois Grieu <fgrieu@gmail.com>
wrote:
Quote:
>Hello, I'm asking myself all kind of questions on allocating
>an array of struct with proper alignment.
>
>Is the following code oorrect ?
>
>I'm most interested by the statement
t = malloc(n*sizeof(r))
>and (to a degree) by the surrounding error checking.
>
>
>#include <stdlib.h>
>
>// a record of system-dependent size and alignment
>typedef struct r
{
char f0;
long f1;
char f2;
} r;
>
>int main(int argc, char *argv[])
{
long n; // number of elements to allocate
r *t; // array of n records of type r
if (argc==2 && // check argv[1] is our single parameter
(n = atol(argv[1]))>0 && // convert to a positive number
atol is not a very good function for this purpose. Better to use
strtol and take advantage of its error checking capabilities prior to
using the result in the if.
Quote:
(size_t)(n*sizeof(r))/n==sizeof(r) && // check for size overflow
What is the type of the product of a long and a size_t. Not just on
your system but in general. If size_t is an unsigned int, I think the
result would be a long and overflow could occur. Better to eliminate
the possibility and move the cast inside the parentheses to get
((size_t)n*sizeof(r))
Even better still would be to change n to a size_t and use strtoul
instead of strtol or atol above.
Quote:
// allocate n records of type r; is that OK ?
(t = malloc(n*sizeof(r)))!=NULL)
1 - Your parentheses are unbalanced. You are missing a ).
2 - Wouldn't you like to be able to put out a different error message
depending on whether argc was not 2 or malloc failed or ...?
While the short-circuit mechanism inherent in && can make this complex
if logically correct, it is a maintenance nightmare.
Quote:
{
// some use the array of n records
long j;
for(j=0;j<n;++j)
t[j].f1 = j; // use a (conseivably) aligned field
Under what conditions would you expect an array element or struct
member to not be aligned?
Quote:
free(t);
}
return 0;
}
>
>
>On systems where alignment must occur for proper acess to
>the field f1, is sizeof(r) guaranteed to be rounded up
Consider the havoc it would cause if you defined a simple array of
struct and the size was not rounded up as needed. Yes it is
guaranteed.
Quote:
>appropriately, and/or malloc guaranteed to return approriately
>aligned memory ?
malloc and friends are also guaranteed to return an address properly
aligned for any and every possible type of object, scalar or
aggregate.
Quote:
>
>Is the calloc() library function guaranteed to perform something
>extra (beside zeroing the allocated memory) ? like, perhaps,
>rounding up the size passed, or checking that the product does
On what basis would it round up more than the product? It has no idea
what type of pointer you are assigning the resulting address to.
Quote:
>not overflow, or making extra alignment ?
Since the alignment is guaranteed to be suitable for any type of
object, what possible extra alignment is there?
Since calloc allocates space for an array and size_t can hold the size
of the largest possible array, I suggest that consistency demands that
passing parameters to calloc where the product would exceed SIZE_MAX
invokes undefined behavior
Quote:
>
>As an aside: one of my C compilers barks if I change sizeof(r)
>to sizeof r. Is this compiler defective ? No it is NOT C++.
The parentheses are required unless the operand is an object. r is
not an object. It is a typedef alias for struct r and both
expressions are types, not objects. You could use *t with or without
parentheses since *t is an object of type r. Any of your compilers
that do not bark on sizeof r are broken.
Remove del for email