473,394 Members | 2,100 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

A malloc question

What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.

/Why Tea

Dec 28 '06 #1
40 2511
Why Tea a écrit :
What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.

/Why Tea
In my opinion it must point to p+1. Since p is a pointer
to SomeStruct, p+1 points to the second structure
in the table.

Dec 28 '06 #2
Why Tea wrote:
What happens to the pointer below?
SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */
Seems to me there is no guarantee it will.
Hello there,

The pointer arithmatic works according to the `type' of the pointer
`p'
that is `SomeStruct'.
So, the returned pointer should point to the 2'nd struct in the
dynamically
allocated array.

---
Regards
-PJP
http://www.cdacbangalore.in/~prasad

Dec 28 '06 #3


On Thu, 28 Dec 2006, jacob navia wrote:
Why Tea a écrit :
>What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.

/Why Tea

In my opinion it must point to p+1. Since p is a pointer
to SomeStruct, p+1 points to the second structure
in the table.
Assuming of course that a valid declaration of malloc() is in scope (e.g.
via #include <stdlib.h>), and the memory allocation succeeded. Otherwise,
the behavior is undefined.

Emil
Dec 28 '06 #4

Why Tea wrote:
What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.
Yes, there is no guarantee. You did not check if your allocation is
successful or not before returning the pointer.

Dec 28 '06 #5
Why Tea said:
What happens to the pointer below?

SomeStruct *p;
p = malloc(100*sizeof(SomeStruct)); /* without a cast */
return((void *)(p+1)); /* will the returned pointer point
to the 2nd struct? */

Seems to me there is no guarantee it will.
Provided you have a prototype in scope for malloc (i.e. you have included
<stdlib.h>), and provided malloc did not return NULL (which you do not
check), the returned pointer will indeed point to space properly aligned
for the SomeStruct type, at an offset of sizeof(SomeStruct) from the
beginning of the allocated block. This is guaranteed by the Standard
(subject to the caveats I mentioned).

It is never necessary or desirable to cast the value returned by malloc
(unless your name is P J Plauger, which, in your case, presumably it
isn't).

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 28 '06 #6
It is never necessary or desirable to cast the value returned by malloc
(unless your name is P J Plauger, which, in your case, presumably it
isn't).
Thanks for the answer. No, I', not P J :), so no cast for me...

One more question while I'm at it about the memory stuff. Assuming I
have the following code:

SomeStruct *p;
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of
sizeof(SomeStruct) */
/* do something before freeing it */
free(p);

Will the entire memory pointed to by p be released? Does free(p) always
releases multiples of the data structure p points to?

Dec 28 '06 #7
Why Tea said:

<snip>
One more question while I'm at it about the memory stuff. Assuming I
have the following code:

SomeStruct *p;
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of
sizeof(SomeStruct) */
/* do something before freeing it */
free(p);

Will the entire memory pointed to by p be released? Does free(p) always
releases multiples of the data structure p points to?
malloc() doesn't allocate data structures. It simply allocates a block of
memory, n bytes in size (where you supply n), and returns a pointer to the
start of that block. In this case, you calculate n like this: 100 +
sizeof(SomeStruct). But malloc doesn't see that calculation. It only sees
the result. It doesn't know about SomeStruct, let alone sizeof(SomeStruct).
It only sees 123, or 145, or whatever it is that 100+sizeof(SomeStruct)
evaluates to. It will try to allocate that much memory, and return a
pointer to that memory if successful.

When you pass that pointer value to free(), the whole block is freed, and
the pointer value becomes indeterminate.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 28 '06 #8
In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */
Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.

-- Richard

--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 28 '06 #9

Richard Tobin wrote:
In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */

Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.
Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.

My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?

Dec 28 '06 #10
Why Tea wrote:
Richard Tobin wrote:
>In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:
>>p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */
Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.

Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.

My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
Padding bytes are part of the struct, and so are included
in the sizeof count. But that doesn't solve the problem of
getting proper alignment for the UserStruct part! Imagine

typedef struct { int x; } SomeStruct;
typedef struct { double y; } UserStruct;

and suppose (1) that there are no padding bytes, (2) that an
int occupies four bytes and must be aligned on a four-byte
boundary, and (3) that a double occupies eight bytes and must
be aligned on an eight-byte boundary. Then the code above will
request twelve bytes, and the allocated memory will begin on an
eight-byte boundary (because the memory returned by malloc() is
properly aligned for any use whatever, hence it's aligned at
least as strictly as a double would require). If p points to
an eight-byte boundary, then p+1 points four bytes further
along, to a four-byte boundary that is not an eight-byte
boundary, and a UserStruct can't begin there.

Things will work all right if UserStruct's alignment is no
stricter than SomeStruct's, but there's no a priori way to know
that this is true. If the actual type of UserStruct is known
(and not just its size), the simplest approach may be

struct { SomeStruct s; UserStruct u; } *p;
p = malloc(sizeof *p);
if (p == NULL) ...
p->s.x = 42;
p->u.y = 42.0;
...
free (p);

In a situation where only sizeof(UserStruct) is known and
not its actual type, a traditional but slightly iffy approach
is to try to figure out what the strictest alignment is:

typedef struct {
int i; long l; long long ll;
float f; double d; long double ld;
char *cp; int *ip; long *lp; long long *llp;
float *fp; double *dp; long double *ldp;
struct whocares *sp;
union whoknows *up;
void (*funcp)(void);
} Worst;
#define PADDED(n) ( ((n) + sizeof(Worst) - 1) \
/ sizeof(Worst) * sizeof(Worst) )
SomeStruct *p = malloc(PADDED(sizeof(SomeStruct))
+ size_of_user_struct);
if (p == NULL) ...
/* Now p points to the SomeStruct, and
* (char*)p + PADDED(sizeof(SomeStruct))
* points to the UserStruct
*/

One drawback to this approach is that it may overestimate
the strictness of UserStruct's alignment. Another is that it's
not possible to enumerate all possible types in the Worst
definition ...

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 28 '06 #11
Why Tea wrote:
Richard Tobin wrote:
In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */
Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.

Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.

My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
Padding bytes in SomeStruct are included in the result of sizeof, but
what happens if UserStruct has stricter alignment requirements than
SomeStruct? Consider

struct SS {
char x;
};
struct US {
long x;
};

sizeof(struct SS) is probably one, but dynamically allocating memory
and storing a struct US one byte after an aligned address is not likely
to work.

(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)

Dec 28 '06 #12
Harald van Dijk wrote:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 28 '06 #13
Eric Sosman wrote:
Harald van Dijk wrote:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)

You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.
I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)") The
same possible values for pointers to structures means the same
alignment for the actual structures.

Dec 28 '06 #14
In article <11*********************@i12g2000cwa.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:
>Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.

My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
No. The padding inside SomeStruct and UserStruct are included in there
sizes, but you may need padding *between* them which is not part of
either.

If you know the structs, I think the simplest thing to do is declare
a third struct containing them:

struct mystruct {SomeStruct a; UserStruct b;} *p;

and allocate sizeof(*p).

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 28 '06 #15
Harald van Dijk wrote:
Eric Sosman wrote:
>Harald van Dijk wrote:
>>[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.

I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)") The
same possible values for pointers to structures means the same
alignment for the actual structures.
The quoted section doesn't seem to have much to do with
pointers, but I agree that all struct pointers have the same
representation (because the Standard says so, in 6.2.5/26).

However, a shared representation does not imply a common
universe of values! The value of a representation depends on
the type of the expression that accesses it. A particular
representation R (a "bit pattern," if that's more down-to-earth)
may be a value for a `struct S*' but a trap representation for a
`struct T*'. A pointer representation that doesn't satisfy the
alignment requirements of the pointed-to type is not a value
(in the sense that C uses the term) but a trap representation.

Note that "trap representation" does not imply that a trap
will necessarily occur on all attempted uses of the non-value.
Section 6.2.6.1/5 merely says that the behavior is undefined if
a trap representation is treated as a value. In particular, it
may be possible to perform arithmetic on an improperly-aligned
pointer in order to derive one that is properly aligned -- but
then again, it may not be.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 28 '06 #16
In article <en***********@pc-news.cogsci.ed.ac.uk>, I wrote:
>If you know the structs, I think the simplest thing to do is declare
a third struct containing them:
On the other hand, if you *don't* know the structs (which after rereading
your message I think is the situation), you will have more trouble.
Of course, in that case you don't know how much space to allocate.
Does the user pass in the size? Or are you just telling them there's
100 bytes available?

There are various tricks that give you a fairly reliable maximum
required alignment, but perhaps it might be better to re-order the
structures, and put the user one first. Then you can declare

struct mystruct {char space[100]; SomeStruct a;} *p;

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 28 '06 #17
Eric Sosman wrote:
Harald van Dijk wrote:
Eric Sosman wrote:
Harald van Dijk wrote:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.
I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)") The
same possible values for pointers to structures means the same
alignment for the actual structures.

The quoted section doesn't seem to have much to do with
pointers, but I agree that all struct pointers have the same
representation (because the Standard says so, in 6.2.5/26).

However, a shared representation does not imply a common
universe of values!
You're right that 6.10.1p3 doesn't have anything to do with struct
pointers, but it clarifies what "same representation" implies. So, if
you believe it doesn't imply the same set of values, what do you think
the quoted sentence of 6.10.1p3 means?

Dec 28 '06 #18

Eric Sosman wrote:
Why Tea wrote:
Richard Tobin wrote:
In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:

p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */
Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.
Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.

My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?

Padding bytes are part of the struct, and so are included
in the sizeof count. But that doesn't solve the problem of
getting proper alignment for the UserStruct part! Imagine

typedef struct { int x; } SomeStruct;
typedef struct { double y; } UserStruct;

and suppose (1) that there are no padding bytes, (2) that an
int occupies four bytes and must be aligned on a four-byte
boundary, and (3) that a double occupies eight bytes and must
be aligned on an eight-byte boundary. Then the code above will
request twelve bytes, and the allocated memory will begin on an
eight-byte boundary (because the memory returned by malloc() is
properly aligned for any use whatever, hence it's aligned at
least as strictly as a double would require). If p points to
an eight-byte boundary, then p+1 points four bytes further
along, to a four-byte boundary that is not an eight-byte
boundary, and a UserStruct can't begin there.

Things will work all right if UserStruct's alignment is no
stricter than SomeStruct's, but there's no a priori way to know
that this is true. If the actual type of UserStruct is known
(and not just its size), the simplest approach may be

struct { SomeStruct s; UserStruct u; } *p;
p = malloc(sizeof *p);
if (p == NULL) ...
p->s.x = 42;
p->u.y = 42.0;
...
free (p);

In a situation where only sizeof(UserStruct) is known and
not its actual type, a traditional but slightly iffy approach
is to try to figure out what the strictest alignment is:

typedef struct {
int i; long l; long long ll;
float f; double d; long double ld;
char *cp; int *ip; long *lp; long long *llp;
float *fp; double *dp; long double *ldp;
struct whocares *sp;
union whoknows *up;
void (*funcp)(void);
} Worst;
#define PADDED(n) ( ((n) + sizeof(Worst) - 1) \
/ sizeof(Worst) * sizeof(Worst) )
SomeStruct *p = malloc(PADDED(sizeof(SomeStruct))
+ size_of_user_struct);
if (p == NULL) ...
/* Now p points to the SomeStruct, and
* (char*)p + PADDED(sizeof(SomeStruct))
* points to the UserStruct
*/

One drawback to this approach is that it may overestimate
the strictness of UserStruct's alignment. Another is that it's
not possible to enumerate all possible types in the Worst
definition ...
Eric, thanks for the very detailed answer. But there is still something
that is not clear to me.
Suppose the following:
sizeof(SomeStruct) = 8
sizeof(UserStruct) = 16
malloc() will see a request of 24 byte allocation. How does it work out
whether alignment is at 4 byte, 8 byte or 16 byte boundary?

Based on the assumption above, if we were to assume the stricter
UserStruct comes first, will it avoid the problem?

/Why Tea

Dec 28 '06 #19
Why Tea wrote:
Eric Sosman wrote:
Why Tea wrote:
Richard Tobin wrote:
>In article <11**********************@42g2000cwt.googlegroups. com>,
>Why Tea <yt****@gmail.comwrote:
>>
>>p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
>>/* do something before freeing it */
>Be sure you know what you're doing here. You can't, for example,
>reliably store 100 chars followed by a struct in this memory, because
>the alignment of p+100 may not be suitable for the struct.
>
Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:
>
|<- SomeStruct ->|<- UserStruct ->
>
Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);
>
(p+1) points to the beginning of UserStruct, so users can store
anything in there.
>
My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
Padding bytes are part of the struct, and so are included
in the sizeof count. But that doesn't solve the problem of
getting proper alignment for the UserStruct part! Imagine

typedef struct { int x; } SomeStruct;
typedef struct { double y; } UserStruct;

and suppose (1) that there are no padding bytes, (2) that an
int occupies four bytes and must be aligned on a four-byte
boundary, and (3) that a double occupies eight bytes and must
be aligned on an eight-byte boundary. Then the code above will
request twelve bytes, and the allocated memory will begin on an
eight-byte boundary (because the memory returned by malloc() is
properly aligned for any use whatever, hence it's aligned at
least as strictly as a double would require). If p points to
an eight-byte boundary, then p+1 points four bytes further
along, to a four-byte boundary that is not an eight-byte
boundary, and a UserStruct can't begin there.

Things will work all right if UserStruct's alignment is no
stricter than SomeStruct's, but there's no a priori way to know
that this is true. If the actual type of UserStruct is known
(and not just its size), the simplest approach may be

struct { SomeStruct s; UserStruct u; } *p;
p = malloc(sizeof *p);
if (p == NULL) ...
p->s.x = 42;
p->u.y = 42.0;
...
free (p);

In a situation where only sizeof(UserStruct) is known and
not its actual type, a traditional but slightly iffy approach
is to try to figure out what the strictest alignment is:

typedef struct {
int i; long l; long long ll;
float f; double d; long double ld;
char *cp; int *ip; long *lp; long long *llp;
float *fp; double *dp; long double *ldp;
struct whocares *sp;
union whoknows *up;
void (*funcp)(void);
} Worst;
#define PADDED(n) ( ((n) + sizeof(Worst) - 1) \
/ sizeof(Worst) * sizeof(Worst) )
SomeStruct *p = malloc(PADDED(sizeof(SomeStruct))
+ size_of_user_struct);
if (p == NULL) ...
/* Now p points to the SomeStruct, and
* (char*)p + PADDED(sizeof(SomeStruct))
* points to the UserStruct
*/

One drawback to this approach is that it may overestimate
the strictness of UserStruct's alignment. Another is that it's
not possible to enumerate all possible types in the Worst
definition ...

Eric, thanks for the very detailed answer. But there is still something
that is not clear to me.
Suppose the following:
sizeof(SomeStruct) = 8
sizeof(UserStruct) = 16
malloc() will see a request of 24 byte allocation. How does it work out
whether alignment is at 4 byte, 8 byte or 16 byte boundary?
malloc doesn't work this out. It always allocates maximally aligned
blocks of memory. (Keep in mind that a 16-byte aligned block is also
8-byte and 4-byte aligned.) What "maximally aligned" is depends on your
processor and operating system, not on your program, so this only has
to be determined once, and that is when your implementation of the
standard library was written.
Based on the assumption above, if we were to assume the stricter
UserStruct comes first, will it avoid the problem?
Unfortunately, it won't, since it's also just as possible that
SomeStruct has stricter alignment requirements.

Dec 28 '06 #20
Why Tea wrote:
Eric Sosman wrote:
>Why Tea wrote:
>>Richard Tobin wrote:
In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:

p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */
Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.
Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.

My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
Padding bytes are part of the struct, and so are included
in the sizeof count. But that doesn't solve the problem of
getting proper alignment for the UserStruct part! Imagine

typedef struct { int x; } SomeStruct;
typedef struct { double y; } UserStruct;

and suppose (1) that there are no padding bytes, (2) that an
int occupies four bytes and must be aligned on a four-byte
boundary, and (3) that a double occupies eight bytes and must
be aligned on an eight-byte boundary. Then the code above will
request twelve bytes, and the allocated memory will begin on an
eight-byte boundary (because the memory returned by malloc() is
properly aligned for any use whatever, hence it's aligned at
least as strictly as a double would require). If p points to
an eight-byte boundary, then p+1 points four bytes further
along, to a four-byte boundary that is not an eight-byte
boundary, and a UserStruct can't begin there.

Things will work all right if UserStruct's alignment is no
stricter than SomeStruct's, but there's no a priori way to know
that this is true. If the actual type of UserStruct is known
(and not just its size), the simplest approach may be

struct { SomeStruct s; UserStruct u; } *p;
p = malloc(sizeof *p);
if (p == NULL) ...
p->s.x = 42;
p->u.y = 42.0;
...
free (p);

In a situation where only sizeof(UserStruct) is known and
not its actual type, a traditional but slightly iffy approach
is to try to figure out what the strictest alignment is:

typedef struct {
int i; long l; long long ll;
float f; double d; long double ld;
char *cp; int *ip; long *lp; long long *llp;
float *fp; double *dp; long double *ldp;
struct whocares *sp;
union whoknows *up;
void (*funcp)(void);
} Worst;
#define PADDED(n) ( ((n) + sizeof(Worst) - 1) \
/ sizeof(Worst) * sizeof(Worst) )
SomeStruct *p = malloc(PADDED(sizeof(SomeStruct))
+ size_of_user_struct);
if (p == NULL) ...
/* Now p points to the SomeStruct, and
* (char*)p + PADDED(sizeof(SomeStruct))
* points to the UserStruct
*/

One drawback to this approach is that it may overestimate
the strictness of UserStruct's alignment. Another is that it's
not possible to enumerate all possible types in the Worst
definition ...

Eric, thanks for the very detailed answer. But there is still something
that is not clear to me.
Suppose the following:
sizeof(SomeStruct) = 8
sizeof(UserStruct) = 16
malloc() will see a request of 24 byte allocation. How does it work out
whether alignment is at 4 byte, 8 byte or 16 byte boundary?
Since malloc() is part of the implementation, it can use
"insider information" that isn't available outside the boardroom.
Among other things, malloc() knows the alignment requirements of
all types on its own implementation. For example, malloc() might
"just know" that on a particular machine the strictest alignment
required for any type at all is eight bytes; knowing this, malloc()
can simply return eight-byte-aligned memory for every request, and
then it doesn't need to worry about whether the caller will use the
memory for three eight-byte longs or twelve two-byte shorts or
twenty-four characters or a struct of several elements or ...

The C Standard says that a successful malloc() obtains memory
that is "suitably aligned so that it may be assigned to a pointer
to any type of object and then used to access such an object." In
effect, the Standard not only sanctions but requires malloc() to
use the strategy outlined above. There is an angels-on-pinheads
quibble about whether malloc(4), say, needs to satisfy alignment
requirements that only apply to objects of eight bytes or larger;
if long and double and long double are the only types requiring
eight-byte alignment and they are all eight bytes long, clearly
the caller is not going to store one of them (or a struct that
holds one of them) in the memory obtained by malloc(4). If the
program does so it invokes undefined behavior anyhow, so malloc(4)
might return a more loosely-aligned memory block. Whether this is
legal or not has been debated a few times; both sides of the argument
have their adherents.
Based on the assumption above, if we were to assume the stricter
UserStruct comes first, will it avoid the problem?
Probably. It is conceivable, I suppose, that a bizarre machine
might have alignment requirements that are not multiples of each
other: four-byte alignment for int, say, and ten-byte alignment
for long double. On such a machine the only way an int and a
long double could be adjacent would be if one was just before and
one just after a twenty-byte boundary -- and since malloc() would
need to return twenty-byte-aligned memory, it would never be
possible to juxtapose the two objects at the start of a malloc'ed
memory area. (The second would always be mis-aligned, no matter
which one it was.) Personally, I have never run into a machine
with such bizarre alignment requirements and I never expect to,
but the C Standard doesn't rule it out.

A more practical problem is to determine which of the two
types has the stricter alignment. There's a cute little hack
floating about that lets you make a pretty good guess about the
alignment needed for a known type -- Google +alignof +offsetof --
but you need the actual type name, not just the type's size.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 28 '06 #21
Harald van Dijk wrote:
Eric Sosman wrote:
>Harald van Dijk wrote:
>>[...] (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)") [...]

The quoted section doesn't seem to have much to do with
pointers, but I agree that all struct pointers have the same
representation (because the Standard says so, in 6.2.5/26).

You're right that 6.10.1p3 doesn't have anything to do with struct
pointers, but it clarifies what "same representation" implies. So, if
you believe it doesn't imply the same set of values, what do you think
the quoted sentence of 6.10.1p3 means?
It means that the preprocessor does arithmetic as if in
the widest integer type supported by the run-time environment.
I don't think it clarifies "same representation" at all; it
just uses the phrase to describe something else. In particular,
it doesn't say or imply that every bag of bits is a value, not
even for integers (which it mentions), much less for pointers
(which it doesn't).

--
Eric Sosman
es*****@acm-dot-org.invalid

Dec 28 '06 #22
Eric Sosman wrote:
The C Standard says that a successful malloc() obtains memory
that is "suitably aligned so that it may be assigned to a pointer
to any type of object and then used to access such an object." In
effect, the Standard not only sanctions but requires malloc() to
use the strategy outlined above. There is an angels-on-pinheads
quibble about whether malloc(4), say, needs to satisfy alignment
requirements that only apply to objects of eight bytes or larger;
if long and double and long double are the only types requiring
eight-byte alignment and they are all eight bytes long, clearly
the caller is not going to store one of them (or a struct that
holds one of them) in the memory obtained by malloc(4). If the
program does so it invokes undefined behavior anyhow, so malloc(4)
might return a more loosely-aligned memory block. Whether this is
legal or not has been debated a few times; both sides of the argument
have their adherents.
In a comment about the requirement that FILE be a complete type, I
mentioned that the TenDRA compiler needed a magic FILE * distinct from
all others, and it obtained this via xmalloc(FILE), which is a macro
essentially expanding to (FILE *) malloc(sizeof(FILE)), except with
better error checking. Since it would never be dereferenced anyway, I
thought (FILE *) malloc(1) would be a fix in case FILE is allowed to be
an incomplete type in a future standard. You're saying it may not be?

Dec 28 '06 #23
Eric Sosman wrote:
Harald van Dijk wrote:
Eric Sosman wrote:
Harald van Dijk wrote:
[...] (If you disagree, could you explain what is meant by
6.10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t deï¬ned in the header <stdint.h>.142)")[...]

The quoted section doesn't seem to have much to do with
pointers, but I agree that all struct pointers have the same
representation (because the Standard says so, in 6.2.5/26).
You're right that 6.10.1p3 doesn't have anything to do with struct
pointers, but it clarifies what "same representation" implies. So, if
you believe it doesn't imply the same set of values, what do you think
the quoted sentence of 6.10.1p3 means?

It means that the preprocessor does arithmetic as if in
the widest integer type supported by the run-time environment.
How can it mean that, when you argue that "same representation" only
applies to values common to both types?
I don't think it clarifies "same representation" at all; it
just uses the phrase to describe something else. In particular,
it doesn't say or imply that every bag of bits is a value, not
even for integers (which it mentions), much less for pointers
(which it doesn't).
It seems to me that it means that all valid values of type intmax_t and
uintmax_t are valid values of type int and unsigned int (and a bit more
than just that, too) in #if expressions, and I believe you're using
different wording to say that very same thing in this case.

Dec 28 '06 #24
Harald van Dijk wrote:
Eric Sosman wrote:
> The C Standard says that a successful malloc() obtains memory
that is "suitably aligned so that it may be assigned to a pointer
to any type of object and then used to access such an object." In
effect, the Standard not only sanctions but requires malloc() to
use the strategy outlined above. There is an angels-on-pinheads
quibble about whether malloc(4), say, needs to satisfy alignment
requirements that only apply to objects of eight bytes or larger;
if long and double and long double are the only types requiring
eight-byte alignment and they are all eight bytes long, clearly
the caller is not going to store one of them (or a struct that
holds one of them) in the memory obtained by malloc(4). If the
program does so it invokes undefined behavior anyhow, so malloc(4)
might return a more loosely-aligned memory block. Whether this is
legal or not has been debated a few times; both sides of the argument
have their adherents.

In a comment about the requirement that FILE be a complete type, I
mentioned that the TenDRA compiler needed a magic FILE * distinct from
all others, and it obtained this via xmalloc(FILE), which is a macro
essentially expanding to (FILE *) malloc(sizeof(FILE)), except with
better error checking. Since it would never be dereferenced anyway, I
thought (FILE *) malloc(1) would be a fix in case FILE is allowed to be
an incomplete type in a future standard. You're saying it may not be?
I think your dodge is required to work, because the Standard
requires that the returned pointer be assignable to any object
pointer. malloc(1) could deduce that the memory would not be used
to hold a multi-byte tightly-aligned object and could therefore
supply loosely-aligned memory to satisfy the request, but it could
only do so if nothing Evil would happen when the returned value is
assigned to the pointer: No low-order bits sheared off or anything
untoward of that nature. On a machine where pointers come in
different flavors I think malloc(1) would be prohibited from taking
liberties. Whether it could do so on more "uniformly addressed"
machines is the topic of the unresolved (and let's not reopen it
yet again) debate.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 28 '06 #25
Eric Sosman wrote:
Harald van Dijk wrote:
Eric Sosman wrote:
The C Standard says that a successful malloc() obtains memory
that is "suitably aligned so that it may be assigned to a pointer
to any type of object and then used to access such an object." In
effect, the Standard not only sanctions but requires malloc() to
use the strategy outlined above. There is an angels-on-pinheads
quibble about whether malloc(4), say, needs to satisfy alignment
requirements that only apply to objects of eight bytes or larger;
if long and double and long double are the only types requiring
eight-byte alignment and they are all eight bytes long, clearly
the caller is not going to store one of them (or a struct that
holds one of them) in the memory obtained by malloc(4). If the
program does so it invokes undefined behavior anyhow, so malloc(4)
might return a more loosely-aligned memory block. Whether this is
legal or not has been debated a few times; both sides of the argument
have their adherents.
In a comment about the requirement that FILE be a complete type, I
mentioned that the TenDRA compiler needed a magic FILE * distinct from
all others, and it obtained this via xmalloc(FILE), which is a macro
essentially expanding to (FILE *) malloc(sizeof(FILE)), except with
better error checking. Since it would never be dereferenced anyway, I
thought (FILE *) malloc(1) would be a fix in case FILE is allowed to be
an incomplete type in a future standard. You're saying it may not be?

I think your dodge is required to work, because the Standard
requires that the returned pointer be assignable to any object
pointer. malloc(1) could deduce that the memory would not be used
to hold a multi-byte tightly-aligned object and could therefore
supply loosely-aligned memory to satisfy the request, but it could
only do so if nothing Evil would happen when the returned value is
assigned to the pointer: No low-order bits sheared off or anything
untoward of that nature. On a machine where pointers come in
different flavors I think malloc(1) would be prohibited from taking
liberties.
Ah, okay. Basically, malloc() need only behave "as if" it returns a
maximally aligned object? In that case, I agree.
Whether it could do so on more "uniformly addressed"
machines is the topic of the unresolved (and let's not reopen it
yet again) debate.
Alrighty.

Dec 28 '06 #26
On 28 Dec 2006 11:33:33 -0800, "Why Tea" <yt****@gmail.comwrote:
>
Richard Tobin wrote:
>In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:
p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */

Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.

Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.
Maybe, maybe not. p+1 evaluates to the address 1 byte beyond
SomeStruct. Whether that address is suitable for UserStruct depends
on the sizeof(SomeStruct) and the alignment requirements of
UserStruct. I don't know of any way to determine the latter portably.
>
My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
Only if the sizeof(SomeStruct) is an integral multiple of
sizeof(UserStruct). What if sizeof(someStruct) is 4 but UserStruct
requires 8-byte alignment?
Remove del for email
Dec 29 '06 #27
In article <qb********************************@4ax.com>,
Barry Schwarz <sc******@doezl.netwrote:
>p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
>>(p+1) points to the beginning of UserStruct, so users can store
anything in there.
>Maybe, maybe not. p+1 evaluates to the address 1 byte beyond
SomeStruct.
You don't mean that. It points to the address immediately after
SomeStruct. If you have a row of bricks packed together, each of
which is a whole number of inches long, the second doesn't start
"1 inch" beyond the first.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 29 '06 #28
"=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=" <tr*****@gmail.comwrote:
Eric Sosman wrote:
Harald van D=C4=B3k wrote:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.

I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6=2E10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t de=EF=AC=81ned in the header <stdint.h>.142)") The
^^^^^^^^
Don't do that for ASCII characters.
same possible values for pointers to structures means the same
alignment for the actual structures.
No, it doesn't. You're supposing that "the same representation" means
"_all_ the same possible values". It doesn't. It means that the value 1
in type struct a *, must have the same representation as the value 1 in
type struct b *, _if_ 1 is a valid value in both types. IOW, it means
that the same bit pattern, _if_ it is not a trap value, is the same
value. It doesn't require the if to be always true.
For example:

struct small {
small_type x;
};
struct large {
large_type y;
};

Now struct small can have less strict alignment issues than struct
large. Say, for example, that struct small has byte alignment, and
struct large two byte alignment. Then every even (FPVO) P is both a
struct large * and a struct small *; but P+1 will be a valid struct
small *, but not a struct large *; and P+2 will be both a valid struct
large * and a struct small * again.
Or, to look at it another way: if memcmp(str_large_ptr, str_small_ptr)
equals zero, then str_large_ptr must == str_small_ptr; but not all
struct small *s need have struct large *s which compare equal using
either memcmp() or ==.

Richard
Dec 29 '06 #29
Richard Bos wrote:
"=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=" <tr*****@gmail.comwrote:
Eric Sosman wrote:
Harald van D=C4=B3k wrote:
[...]
(Technically, I believe the all structures are required to have the
same alignment. In practice, they don't, and shouldn't.)
>
You're probably thinking about pointers to structs, not
about structs. All pointers to all types of structs have the
same representation and alignment requirements, but that's
just the pointer itself: The thing it points to has its own
idiosyncratic alignment and representation.
I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6=2E10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t de=EF=AC=81ned in the header <stdint.h>.142)") The
^^^^^^^^
Don't do that for ASCII characters.
I don't do that myself. The PDF reader I used here -- KPDF -- copies
what appears as "defined" as "de\uFB01ned", and '\uFB01' ("LATIN SMALL
LIGATURE FI") is not an ASCII character, so it gets encoded. I don't
know how it is stored internally in n1124, so I don't know if this is
correct, but I suspect it is.
same possible values for pointers to structures means the same
alignment for the actual structures.

No, it doesn't. You're supposing that "the same representation" means
"_all_ the same possible values". It doesn't.
Then, as I asked Eric Sosman, what do you believe the quoted sentence
of 6.10.1p3 is meant to guarantee?

Dec 29 '06 #30
Harald van Dijk wrote:
Eric Sosman wrote:
>Harald van Dijk wrote:
>>You're right that 6.10.1p3 doesn't have anything to do with struct
pointers, but it clarifies what "same representation" implies. So, if
you believe it doesn't imply the same set of values, what do you think
the quoted sentence of 6.10.1p3 means?
It means that the preprocessor does arithmetic as if in
the widest integer type supported by the run-time environment.

How can it mean that, when you argue that "same representation" only
applies to values common to both types?
I feel as a color-blind person must when someone explains to
him why Monet used aqua to accentuate the greens in Waterlilies.
You are using some chain of reasoning that I simply do not see
at all; it seems (to me) that the quoted passage has nothing to
do with the subject matter, and yet you see some strong connection.
Sorry -- truly sorry -- but I just don't get it and don't know
how to answer your questions.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 29 '06 #31
Eric Sosman wrote:
Harald van Dijk wrote:
Eric Sosman wrote:
Harald van Dijk wrote:
You're right that 6.10.1p3 doesn't have anything to do with struct
pointers, but it clarifies what "same representation" implies. So, if
you believe it doesn't imply the same set of values, what do you think
the quoted sentence of 6.10.1p3 means?
It means that the preprocessor does arithmetic as if in
the widest integer type supported by the run-time environment.
How can it mean that, when you argue that "same representation" only
applies to values common to both types?

I feel as a color-blind person must when someone explains to
him why Monet used aqua to accentuate the greens in Waterlilies.
You are using some chain of reasoning that I simply do not see
at all; it seems (to me) that the quoted passage has nothing to
do with the subject matter, and yet you see some strong connection.
Sorry -- truly sorry -- but I just don't get it and don't know
how to answer your questions.
I'll try to explain it a bit more simply: they (6.2.5p26 and 6.10.1p3)
have in common the phrase "same representation". There are at least two
possible different intended meanings for "same representation":
a) if two types have the same representation, you can safely memcpy()
the values common to both types from one to the other, and read back
the original value
b) if two types have the same representation, you can safely memcpy()
any value from one type to the other, and read back the original value

The replies I have got here suggest that a is used in 6.2.5p26, and b
is used in 6.10.1p3. What I believe is that only one of the meanings
can be used, and it must apply to all occurrences of the phrase.

Dec 29 '06 #32
On 29 Dec 2006 02:27:50 GMT, ri*****@cogsci.ed.ac.uk (Richard Tobin)
wrote:
>In article <qb********************************@4ax.com>,
Barry Schwarz <sc******@doezl.netwrote:
>>p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
>>>(p+1) points to the beginning of UserStruct, so users can store
anything in there.
>>Maybe, maybe not. p+1 evaluates to the address 1 byte beyond
SomeStruct.

You don't mean that. It points to the address immediately after
SomeStruct. If you have a row of bricks packed together, each of
which is a whole number of inches long, the second doesn't start
"1 inch" beyond the first.
Ignoring the bricks for a moment: If sizeof(SomeStruct) is 8 and p
contains 0x1000, the SomeStruct occupies bytes 0x1000 through 0x1007.
p+1 evaluates to 0x1008 which is one byte beyond SomeStruct. Would it
have been better if I had used the exact wording in the standard
(e.g., 6.5.9-6) of "one past the end" of the object. I'm sorry but I
really don't see any difference between "one past the end" and "one
beyond".

Getting back to the bricks (letting the whole number be 8 for
consistency): The first brick starts at inch 0 and extends up to inch
7.999999999999999999999.... The next brick starts immediately after
this which is inch 8. This is obviously zero inches beyond the end of
the first brick. Bytes, on the other had are discrete, not
continuous, at least as far as measurement (distance) is concerned.
Remove del for email
Dec 29 '06 #33

Eric Sosman wrote:
Why Tea wrote:
Richard Tobin wrote:
In article <11**********************@42g2000cwt.googlegroups. com>,
Why Tea <yt****@gmail.comwrote:

p = malloc(100 + sizeof(SomeStruct)); /* 100 is not multiples of sizeof(SomeStruct) */
/* do something before freeing it */
Be sure you know what you're doing here. You can't, for example,
reliably store 100 chars followed by a struct in this memory, because
the alignment of p+100 may not be suitable for the struct.
Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:

|<- SomeStruct ->|<- UserStruct ->

Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);

(p+1) points to the beginning of UserStruct, so users can store
anything in there.

My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?

Padding bytes are part of the struct, and so are included
in the sizeof count. But that doesn't solve the problem of
getting proper alignment for the UserStruct part! Imagine

typedef struct { int x; } SomeStruct;
typedef struct { double y; } UserStruct;

and suppose (1) that there are no padding bytes, (2) that an
int occupies four bytes and must be aligned on a four-byte
boundary, and (3) that a double occupies eight bytes and must
be aligned on an eight-byte boundary. Then the code above will
request twelve bytes, and the allocated memory will begin on an
eight-byte boundary (because the memory returned by malloc() is
properly aligned for any use whatever, hence it's aligned at
least as strictly as a double would require). If p points to
an eight-byte boundary, then p+1 points four bytes further
along, to a four-byte boundary that is not an eight-byte
boundary, and a UserStruct can't begin there.

Things will work all right if UserStruct's alignment is no
stricter than SomeStruct's, but there's no a priori way to know
that this is true. If the actual type of UserStruct is known
(and not just its size), the simplest approach may be

struct { SomeStruct s; UserStruct u; } *p;
p = malloc(sizeof *p);
if (p == NULL) ...
p->s.x = 42;
p->u.y = 42.0;
...
free (p);

In a situation where only sizeof(UserStruct) is known and
not its actual type, a traditional but slightly iffy approach
is to try to figure out what the strictest alignment is:

typedef struct {
int i; long l; long long ll;
float f; double d; long double ld;
char *cp; int *ip; long *lp; long long *llp;
float *fp; double *dp; long double *ldp;
struct whocares *sp;
union whoknows *up;
void (*funcp)(void);
} Worst;
#define PADDED(n) ( ((n) + sizeof(Worst) - 1) \
/ sizeof(Worst) * sizeof(Worst) )
SomeStruct *p = malloc(PADDED(sizeof(SomeStruct))
+ size_of_user_struct);
if (p == NULL) ...
/* Now p points to the SomeStruct, and
* (char*)p + PADDED(sizeof(SomeStruct))
* points to the UserStruct
*/

One drawback to this approach is that it may overestimate
the strictness of UserStruct's alignment. Another is that it's
not possible to enumerate all possible types in the Worst
definition ...
Thanks Eric. Is it possible to have a sample code with some printf's to
show that (p+1) over steps the boundary of the two structs?

Dec 29 '06 #34
In article <fj********************************@4ax.com>,
Barry Schwarz <sc******@doezl.netwrote:
>Ignoring the bricks for a moment: If sizeof(SomeStruct) is 8 and p
contains 0x1000, the SomeStruct occupies bytes 0x1000 through 0x1007.
p+1 evaluates to 0x1008 which is one byte beyond SomeStruct.
No it isn't. It's zero bytes beyond SomeStruct. SomeStruct occupies
byte 1007 and p+1 starts immediately after it. There is no "one byte".
>Would it
have been better if I had used the exact wording in the standard
(e.g., 6.5.9-6) of "one past the end" of the object.
I don't have the standard to hand, but I think that refers to one
*object* after the last *object*. If you'd said one byte after
the last byte of SomeStruct it would have made more sense. One inch
beyond the last inch of an object is different from one inch beyond
the object.
>Getting back to the bricks (letting the whole number be 8 for
consistency): The first brick starts at inch 0 and extends up to inch
7.999999999999999999999.... The next brick starts immediately after
this which is inch 8. This is obviously zero inches beyond the end of
the first brick. Bytes, on the other had are discrete, not
continuous, at least as far as measurement (distance) is concerned.
SomeStruct ends at the end of its last byte, not the beginning of it
(otherwise that byte wouldn't be part of it). Even if bytes were
indivisible, it wouldn't be one byte past the object. If you still
disagree, consider what would be zero bytes past the object? Your
reasoning suggests that the last byte of the object is zero bytes
beyond it.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 29 '06 #35
On 29 Dec 2006 23:20:28 GMT, in comp.lang.c , ri*****@cogsci.ed.ac.uk
(Richard Tobin) wrote:
>In article <fj********************************@4ax.com>,
Barry Schwarz <sc******@doezl.netwrote:
>>Getting back to the bricks
Analogies using linear measurement are flawed because measurement
isn't discrete. As far as C is concerned, bytes are indivisble
discrete objects. Using a continuous medium analogy leads to muddled
thinking...
>>7.999999999999999999999....
....of that sort. ...
>>This is obviously zero inches beyond the end of
the first brick.
....and that. ...
>SomeStruct ends at the end of its last byte,
....more muddle...

Use a row of apples. This makes it easier to see how it works.

The object begins with its first apple, and ends with its last. The
first apple beyond the end of the object is, naturally, one beyond the
end.
>Your reasoning suggests that the last byte of the object is zero bytes
beyond it.
Well, it is! Think about it - the last byte is not one byte beyond the
end of the object, nor one byte before its end. So whats left?
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 30 '06 #36
In article <o9********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.netwrote:
>Use a row of apples. This makes it easier to see how it works.

The object begins with its first apple, and ends with its last. The
first apple beyond the end of the object is, naturally, one beyond the
end.
What an odd view. It's one apple beyond the last apple, but not one
apple beyond the apples.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 30 '06 #37
On 30 Dec 2006 21:28:55 GMT, in comp.lang.c , ri*****@cogsci.ed.ac.uk
(Richard Tobin) wrote:
>In article <o9********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.netwrote:
>>Use a row of apples. This makes it easier to see how it works.

The object begins with its first apple, and ends with its last. The
first apple beyond the end of the object is, naturally, one beyond the
end.

What an odd view. It's one apple beyond the last apple, but not one
apple beyond the apples.
You lost me at the point at which you said the same thing twice, but
implied they were different.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 31 '06 #38
"=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=" <tr*****@gmail.comwrote:
Richard Bos wrote:
"=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=" <tr*****@gmail.comwrote:
I am talking about structures. Pointers to structures, as you mention,
have the same representation. The same representation means the same
possible values. (If you disagree, could you explain what is meant by
6=2E10.1p3? "For the purposes of this [#if expressions] token conversion
and evaluation, all signed integer types and all unsigned integer types
act as if they have the same representation as, respectively, the types
intmax_t and uintmax_t de=EF=AC=81ned in the header <stdint.h>.142)") The
^^^^^^^^
Don't do that for ASCII characters.

I don't do that myself. The PDF reader I used here -- KPDF -- copies
what appears as "defined" as "de\uFB01ned", and '\uFB01' ("LATIN SMALL
LIGATURE FI") is not an ASCII character, so it gets encoded. I don't
know how it is stored internally in n1124, so I don't know if this is
correct, but I suspect it is.
I see. Yes, for PDFs using Unicode it would probably be correct.
same possible values for pointers to structures means the same
alignment for the actual structures.
No, it doesn't. You're supposing that "the same representation" means
"_all_ the same possible values". It doesn't.

Then, as I asked Eric Sosman, what do you believe the quoted sentence
of 6.10.1p3 is meant to guarantee?
It's meant to guarantee, for one thing, that you can do this:

typedef struct node * nodeptr;

struct node {
int payload;
nodeptr next;
}

Richard
Jan 3 '07 #39
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
"=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=" <tr*****@gmail.comwrote:
>Richard Bos wrote:
"=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=" <tr*****@gmail.comwrote:
I am talking about structures. Pointers to structures, as you
mention, have the same representation. The same representation
means the same possible values. (If you disagree, could you
explain what is meant by 6.10.1p3? "For the purposes of this
[#if expressions] token conversion and evaluation, all signed
integer types and all unsigned integer types act as if they
have the same representation as, respectively, the types
intmax_t and uintmax_t defined in the header <stdint.h>.142)")
(I've manually replaced some of the above with plain ASCII characters.)

[...]
>Then, as I asked Eric Sosman, what do you believe the quoted sentence
of 6.10.1p3 is meant to guarantee?

It's meant to guarantee, for one thing, that you can do this:

typedef struct node * nodeptr;

struct node {
int payload;
nodeptr next;
}
I don't see how 6.10.1p3 is relevant to this; there's not a "#if"
expression anywhere in sight.

Incidentally, there are change bars in N1124 in this section, meaning
that the wording was changed post-C99. Here's a quote from the C99
standard:

The resulting tokens compose the controlling constant expression
which is evaluated according to the rules of 6.6, except that
all signed integer types and all unsigned integer types act as
if they have the same representation as, respectively, the types
intmax_t and uintmax_t defined in the header <stdint.h>

And here's the corresponding quote from N1124:

The resulting tokens compose the controlling constant expression
which is evaluated according to the rules of 6.6. For the
purposes of this token conversion and evaluation, all signed
integer types and all unsigned integer types act as if they have
the same representation as, respectively, the types intmax_t and
uintmax_t defined in the header <stdint.h>.

which also adds the following footnote:

Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX
is 0xFFFF, the constant 0x8000 is signed and positive within a #if
expression even though it would be unsigned in translation phase 7.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 3 '07 #40
Eric Sosman wrote:
..., but I agree that all struct pointers have the same
representation (because the Standard says so, in 6.2.5/26).

However, a shared representation does not imply a common
universe of values! The value of a representation depends on
the type of the expression that accesses it. A particular
representation R (a "bit pattern," if that's more down-to-earth)
may be a value for a `struct S*' but a trap representation for a
`struct T*'. A pointer representation that doesn't satisfy the
alignment requirements of the pointed-to type is not a value
(in the sense that C uses the term) but a trap representation.
The statement "All pointers to structure types shall have the same
representation ... as each other" in 6.2.5/26 leaves no room for
restriction to certain values.
Also, I see no wording in the standard which said that a misaligned
pointer would be a trap representation.
--
Dietmar Schindler
Jan 4 '07 #41

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

231
by: Brian Blais | last post by:
Hello, I saw on a couple of recent posts people saying that casting the return value of malloc is bad, like: d=(double *) malloc(50*sizeof(double)); why is this bad? I had always thought...
66
by: Knady | last post by:
Hi, I have the following problem, I must to do my assignment, but I really do not know how to use the malloc. I need create a program that will be used to do some algebrical computation on the...
36
by: Martin Andert | last post by:
Hello, I have a question regarding malloc and free. Here my code sample: int main() { /* allocating dynamic memory for array */ int* array = (int*) malloc(5 * sizeof(int)); /* ... program...
23
by: puzzlecracker | last post by:
Why is "new" a C++ language-level construct while "malloc" is a library function?
8
by: Snis Pilbor | last post by:
First, let me announce that this is very possibly off-topic because malloc is a specific third party accessory to c, etc. I spent about an hour trying to find a more appropriate newsgroup and...
12
by: gooch | last post by:
I originally posted the following code in a group discussing threads but after further research I think I have a c question about the code. I know there are a couple of non standard c includes here...
25
by: Why Tea | last post by:
Thanks to those who have answered my original question. I thought I understood the answer and set out to write some code to prove my understanding. The code was written without any error checking....
24
by: VijaKhara | last post by:
hi all, i am trying to create a dynamic 2D array with size N x 3 (N will be put in as a parameter) using the following code: int **xyz; int i,N; N=30000; xyz=malloc(3*sizeof(int*));
17
by: Christopher Benson-Manica | last post by:
Some recent posts got me thinking about how one might have dealt with simplistic malloc() implementations which might return NULL for a 64K request but might accept two 32K requests or four 16K...
71
by: desktop | last post by:
I have read in Bjarne Stroustrup that using malloc and free should be avoided in C++ because they deal with uninitialized memory and one should instead use new and delete. But why is that a...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.