473,327 Members | 2,007 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,327 software developers and data experts.

Alignment on stack arrays

I understand that a line like

char *a = malloc(64) ;

when succeeding will initialize a to a pointer that is aligned at worst
on the natural boundary of the underlying architecture, possibly on a
multiple thereof.

Now what about

char a[64] ;

Do we have the guarantee that &a[0] is always going to be aligned
according to the same criteria as above?
Jun 27 '08 #1
18 3946
In article <g3**********@registered.motzarella.org>,
H.K. Kingston-Smith <HK***@yahoo.comwrote:
> Now what about

char a[64] ;

Do we have the guarantee that &a[0] is always going to be aligned
according to the same criteria as above?
No. You could use a union to ensure it is aligned suitably for
some particular other type(s).

-- Richard
--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #2
H.K. Kingston-Smith said:
I understand that a line like

char *a = malloc(64) ;

when succeeding will initialize a to a pointer that is aligned at worst
on the natural boundary of the underlying architecture, possibly on a
multiple thereof.
Putting it another way, it will be correctly aligned for any type. That's
because malloc doesn't know what type you're going to use the memory for.
Now what about

char a[64] ;

Do we have the guarantee that &a[0] is always going to be aligned
according to the same criteria as above?
It will be correctly aligned for char on that system. It is not guaranteed (or
even particularly likely) that it will be correctly aligned for any other
(non-char) type.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #3
On Sun, 15 Jun 2008 16:41:09 +0000 (UTC), "H.K. Kingston-Smith"
<HK***@yahoo.comwrote:
> I understand that a line like

char *a = malloc(64) ;

when succeeding will initialize a to a pointer that is aligned at worst
on the natural boundary of the underlying architecture, possibly on a
multiple thereof.
malloc will return an address that is properly aligned for any type of
C object (at least in part because malloc has no idea what the type of
a is). There may well be other objects available in the architecture
with other alignment requirements that malloc knows nothing about.
>
Now what about

char a[64] ;

Do we have the guarantee that &a[0] is always going to be aligned
according to the same criteria as above?
No. In this case, the compiler knows at a[0] is a char and it only
has to align a on a "char boundary".

On most systems char has no alignment requirements, or equivalently is
aligned on a multiple of one, so this is not the best example.
Consider a non-C99 system where long and double are the most stringent
and need to be aligned on an 8-byte boundary while int needs only be
on a 4-byte boundary. malloc must return an address which is a
multiple of 8. But an int (or an array of int) can be aligned on any
multiple of 4 (of which only half are also multiples of 8).
Remove del for email
Jun 27 '08 #4
"H.K. Kingston-Smith" <HK***@yahoo.comwrites:
I understand that a line like

char *a = malloc(64) ;

when succeeding will initialize a to a pointer that is aligned at worst
on the natural boundary of the underlying architecture, possibly on a
multiple thereof.

Now what about

char a[64] ;

Do we have the guarantee that &a[0] is always going to be aligned
according to the same criteria as above?
As others have said, the answer is no.

However, it's fairly likely that a 64-byte object will be more
strictly aligned anyway, simply because it can make some operations
more efficient. For example, if you call

memset(a, 0, sizeof a);

then memset() *might* be able to zero a word at a time if a is
word-aligned.

Don't let the fact that a is *likely* to be word-aligned (whatever a
"word" happens to be) fool you into thinking that it's guaranteed.

Others have also suggested using a union to force it to have a
stricter alignment. That's likely to be good enough, but if you want
the same alignment guarantees provided by malloc(), there's really no
portable way to do it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #5
On Jun 15, 5:41*pm, "H.K. Kingston-Smith" <HK...@yahoo.comwrote:
* * * * I understand that a line like

* * * * char *a = malloc(64) ;

when succeeding will initialize a to a pointer that is aligned at worst
on the natural boundary of the underlying architecture, possibly on a
multiple thereof.

* * * * Now what about

* * * * char a[64] ;

Do we have the guarantee that &a[0] is always going to be aligned
according to the same criteria as above?
I don't know if you actually need a solution or not, but anyway..

If you're happy using pointers to the 'stack' arrays, then perhaps
something like the following. I need a 16-character array to be
aligned to a multiple of 8. An extra 7 bytes are allocated and a
pointer to the array is stepped until the alignment is correct.

This makes some assumptions however about being able to access the
bottom 3 address lines via the pointer value.

#include <stdio.h>

int main(void)
{
char a0[23]; /* Need char a[16] */
char *a=a0;

while ((int)a & 7) ++a;

printf("%x\n",a);

}

--
Bartc
Jun 27 '08 #6
On Jun 15, 11:28 pm, Bart <b...@freeuk.comwrote:
On Jun 15, 5:41 pm, "H.K. Kingston-Smith" <HK...@yahoo.comwrote:
I understand that a line like
char *a = malloc(64) ;
when succeeding will initialize a to a pointer that is aligned at worst
on the natural boundary of the underlying architecture, possibly on a
multiple thereof.
Now what about
char a[64] ;
Do we have the guarantee that &a[0] is always going to be aligned
according to the same criteria as above?

I don't know if you actually need a solution or not, but anyway..

If you're happy using pointers to the 'stack' arrays, then perhaps
something like the following. I need a 16-character array to be
aligned to a multiple of 8. An extra 7 bytes are allocated and a
pointer to the array is stepped until the alignment is correct.

This makes some assumptions however about being able to access the
bottom 3 address lines via the pointer value.
That code snipped makes much more assumptions than just that.
>
#include <stdio.h>

int main(void)
{
char a0[23]; /* Need char a[16] */
char *a=a0;

while ((int)a & 7) ++a;

printf("%x\n",a);

}
That code is rubbish. Please don't recommend code that doesn't work.
Jun 27 '08 #7
On Jun 15, 9:43*pm, vipps...@gmail.com wrote:
On Jun 15, 11:28 pm, Bart <b...@freeuk.comwrote:
#include <stdio.h>
int main(void)
{
char a0[23]; * * /* Need char a[16] */
char *a=a0;
while ((int)a & 7) ++a;
printf("%x\n",a);
}

That code is rubbish. Please don't recommend code that doesn't work
It's not a recommendation. It's just ideas. But as for not working:

#include <stdio.h>

int main(void)
{
char a0[23];
char *a=a0;

printf("Address before: %x\n",a);

while ((int)a & 7) ++a;

printf("Address after: %x\n",a);
}

Output:

Address before: 12ff59
Address after: 12ff60
--
Bartc
Jun 27 '08 #8
Bart <bc@freeuk.comwrites:
[...]
If you're happy using pointers to the 'stack' arrays, then perhaps
something like the following. I need a 16-character array to be
aligned to a multiple of 8. An extra 7 bytes are allocated and a
pointer to the array is stepped until the alignment is correct.

This makes some assumptions however about being able to access the
bottom 3 address lines via the pointer value.

#include <stdio.h>

int main(void)
{
char a0[23]; /* Need char a[16] */
char *a=a0;

while ((int)a & 7) ++a;

printf("%x\n",a);

}
That might be acceptable in system-specific code (though incrementing
the address one at a time is wasteful).

If you want alignment matching a particular type, declare an object of
that type or use a union. If you want alignment appropriate for any
possible type, use malloc.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #9
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
Bart <bc@freeuk.comwrites:
>char a0[23]; /* Need char a[16] */
char *a=a0;

while ((int)a & 7) ++a;
That might be acceptable in system-specific code (though incrementing
the address one at a time is wasteful).
That's true. Maybe it could even be done in the char *a=a0 line. But I
was more likely to get it right this way..
>
If you want alignment matching a particular type, declare an object of
that type or use a union.
Yes, but doesn't the union get in the way? You'd have to use u.a[i]
instead of a[i]. If there already existed lots of references to a, it
would mean many changes and is a little obfuscatory.

Also the obvious solution (to use, for example, int a[16] then access
it as as though it were char a[64]), would have casts sprinkled
everywhere. The use of macros could alleviate these shortcomings
although the global nature of macros might be a problem.

My pointer idea leaves the original code using a[] unchanged but at a
cost of a pointer dereference (plus a few wasted bytes in the array).
This might be acceptable if a word-aligned char buffer in automatic
storage is what's wanted.

--
Bartc
Jun 27 '08 #10
On Jun 16, 12:00 am, Bart <b...@freeuk.comwrote:
On Jun 15, 9:43 pm, vipps...@gmail.com wrote:
On Jun 15, 11:28 pm, Bart <b...@freeuk.comwrote:
#include <stdio.h>
int main(void)
{
char a0[23]; /* Need char a[16] */
char *a=a0;
while ((int)a & 7) ++a;
printf("%x\n",a);
}
That code is rubbish. Please don't recommend code that doesn't work

It's not a recommendation. It's just ideas. But as for not working:

#include <stdio.h>

int main(void)
{
char a0[23];
char *a=a0;

printf("Address before: %x\n",a);

while ((int)a & 7) ++a;

printf("Address after: %x\n",a);

}

Output:

Address before: 12ff59
Address after: 12ff60
What is that supposed to prove?
You invoke undefined behavior in the while loop and in the printf call
and there is no 'return' from main.
Here's a possible fix:
/* a = ... */
while((uintptr_t)a & 7) ++a;
printf("%p\n", (void *)a);

But its purpose I am not aware of.
Jun 27 '08 #11
Bart wrote, On 15/06/08 22:00:
On Jun 15, 9:43 pm, vipps...@gmail.com wrote:
>On Jun 15, 11:28 pm, Bart <b...@freeuk.comwrote:
>>#include <stdio.h>
int main(void)
{
char a0[23]; /* Need char a[16] */
char *a=a0;
while ((int)a & 7) ++a;
printf("%x\n",a);
}
That code is rubbish. Please don't recommend code that doesn't work

It's not a recommendation. It's just ideas. But as for not working:
<snip>

Implementations where pointers are larger than int are becoming popular
again (a lot of 64 bit implementations have this property) and on such
implementations casting the pointer to int invokes undefined behaviour.
It may well still work (and is likely to on a lot of implementations)
but it is not guaranteed and the compiler is under no obligation to make
it work on such systems.
--
Flash Gordon
Jun 27 '08 #12
Bart wrote, On 15/06/08 23:39:
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
>Bart <bc@freeuk.comwrites:
>>char a0[23]; /* Need char a[16] */
char *a=a0;

while ((int)a & 7) ++a;
>That might be acceptable in system-specific code (though incrementing
the address one at a time is wasteful).

That's true. Maybe it could even be done in the char *a=a0 line. But I
was more likely to get it right this way..
Well, it is often said here that one should get it right before worrying
about efficiency, but...
>If you want alignment matching a particular type, declare an object of
that type or use a union.

Yes, but doesn't the union get in the way? You'd have to use u.a[i]
instead of a[i]. If there already existed lots of references to a, it
would mean many changes and is a little obfuscatory.
Why?

char *a = a0.c

Where a0.c is the part of the union that is a char array.
Also the obvious solution (to use, for example, int a[16] then access
it as as though it were char a[64]), would have casts sprinkled
everywhere.
Why?

int a0[WHATEVER];
char *a = (char*)a0;
The use of macros could alleviate these shortcomings
although the global nature of macros might be a problem.

My pointer idea leaves the original code using a[] unchanged but at a
cost of a pointer dereference (plus a few wasted bytes in the array).
This might be acceptable if a word-aligned char buffer in automatic
storage is what's wanted.
There is nothing about the other methods that requires changing the rest
of the code. You used an additional pointer, and that additional pointer
could be used with any other conceivable method!
--
Flash Gordon
Jun 27 '08 #13
On Jun 16, 12:15*am, vipps...@gmail.com wrote:
On Jun 16, 12:00 am, Bart <b...@freeuk.comwrote:
#include <stdio.h>
int main(void)
{
char a0[23];
char *a=a0;
printf("Address before: %x\n",a);
while ((int)a & 7) ++a;
printf("Address after: *%x\n",a);
}
Output:
Address before: 12ff59
Address after: *12ff60

What is that supposed to prove?
That the int representation of a pointer has had it's 3 low bits
changed from 001 to 000. Which is very likely to correspond to the low
bits of the physical address.
You invoke undefined behavior in the while loop and in the printf call
Why? Converting a pointer to an int isn't exactly unheard of. It's
best to use an int big enough to represent the pointer, but I have a
feeling it will just be truncated if not, and I'm only interested in
the bottom 3 bits anyway. The pointer is only changed using ++a.

For printing, again I'm interested in the /int/ representation of the
pointer (also I'd forgotten about %p).
and there is no 'return' from main.
Well my compilers (3 out of 4 anyway) keep insisting on not
complaining about it.. so I'm not going to argue when a 5-line
expression of an /idea/ is at stake.
Here's a possible fix:
/* a = ... */
while((uintptr_t)a & 7) ++a;
printf("%p\n", (void *)a);
Yes nice textbook stuff.
>
But its purpose I am not aware of
Clearly not.

--
Bartc
Jun 27 '08 #14
On Jun 16, 3:05 am, Bart <b...@freeuk.comwrote:
On Jun 16, 12:15 am, vipps...@gmail.com wrote:
On Jun 16, 12:00 am, Bart <b...@freeuk.comwrote:
#include <stdio.h>
int main(void)
{
char a0[23];
char *a=a0;
printf("Address before: %x\n",a);
while ((int)a & 7) ++a;
printf("Address after: %x\n",a);
}
Output:
Address before: 12ff59
Address after: 12ff60
What is that supposed to prove?

That the int representation of a pointer has had it's 3 low bits
changed from 001 to 000. Which is very likely to correspond to the low
bits of the physical address.
It is not guaranteed that int can correctly represent a pointer.
You invoke undefined behavior in the while loop and in the printf call

Why? Converting a pointer to an int isn't exactly unheard of. It's
It is not unheard, so?
best to use an int big enough to represent the pointer, but I have a
int is not guaranteed to be big enough to represent the pointer.
Perhaps you mean integer type big enough; in which case yes, there is
intptr_t and uintptr_t, and indeed it's best to use these.
feeling it will just be truncated if not, and I'm only interested in
the bottom 3 bits anyway. The pointer is only changed using ++a.
It has nothing to do with "truncated".
See 6.3.2.3 p 6
For printing, again I'm interested in the /int/ representation of the
pointer (also I'd forgotten about %p).
What int representation? That doesn't make sense. You are passing
different types than the ones expected in a variadic function/macro
which causes undefined behavior.
and there is no 'return' from main.

Well my compilers (3 out of 4 anyway) keep insisting on not
complaining about it.. so I'm not going to argue when a 5-line
expression of an /idea/ is at stake.
Most likely because you compile with C99 mode, in which is fine not to
return a value from main.
Here's a possible fix:
/* a = ... */
while((uintptr_t)a & 7) ++a;
printf("%p\n", (void *)a);

Yes nice textbook stuff.
But, some lines ago you said it's *best* to use an integer type big
enough.
Jun 27 '08 #15
On Jun 16, 12:12*am, Flash Gordon <s...@flash-gordon.me.ukwrote:
Bart wrote, On 15/06/08 23:39:
Yes, but doesn't the union get in the way? You'd have to use u.a[i]
Why?

char *a = a0.c

Where a0.c is the part of the union that is a char array.
Also the obvious solution (to use, for example, int a[16] then access
it as as though it were char a[64]), would have casts sprinkled
everywhere.

Why?

int a0[WHATEVER];
char *a = (char*)a0;
There is nothing about the other methods that requires changing the rest
of the code. You used an additional pointer, and that additional pointer
could be used with any other conceivable method!
You're completely right. I'd only considered the union and
equivalenced schemes for fast direct access. With an extra pointer
level to play with, there are other, simpler, possibilities than my
idea (although manipulating a pointer like that to play around with
alignments still has uses).

Never mind, the OP now has some concrete examples to look at. And I'm
off to bed..

--
Bartc

Jun 27 '08 #16
Keith Thompson wrote:
>
.... snip ...
>
Others have also suggested using a union to force it to have a
stricter alignment. That's likely to be good enough, but if you
want the same alignment guarantees provided by malloc(), there's
really no portable way to do it.
Which is one of the reasons malloc must be a system supplied
function, along with realloc, free, and calloc.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #17
On Jun 15, 9:28*pm, Bart <b...@freeuk.comwrote:
#include <stdio.h>

int main(void)
{
char a0[23]; * * /* Need char a[16] */
char *a=a0;

while ((int)a & 7) ++a;

printf("%x\n",a);

}
This is quite non-portable. You don't know how (int) a changes when a
is incremented. You seem to think that inrementing a changes the last
three bits in (int) a. That is in no way guaranteed.

Jun 27 '08 #18
On Jun 17, 12:33*am, "christian.bau"
<christian....@cbau.wanadoo.co.ukwrote:
On Jun 15, 9:28*pm, Bart <b...@freeuk.comwrote:
#include <stdio.h>
int main(void)
{
char a0[23]; * * /* Need char a[16] */
char *a=a0;
while ((int)a & 7) ++a;
printf("%x\n",a);
}

This is quite non-portable. You don't know how (int) a changes when a
is incremented. You seem to think that inrementing a changes the last
three bits in (int) a. That is in no way guaranteed.
No, but I did add this comment:

Bart wrote:
...
This makes some assumptions however about being able to access the
bottom 3 address lines via the pointer value.
For this example, there were more direct ways of achieving the
result..

But in general, I think there are many implementations where the lower
bits of a pointer, converted to an int, do directly correspond to
address lines. And in this case why not exploit that? If you can't
mess with this sort of thing in C, what non-ASM language can?

--
Bartc
Jun 27 '08 #19

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

Similar topics

7
by: Rajeev | last post by:
Hello, I'm using gcc 3.4.2 on a Xeon (P4) platform, all kinds of speed optimizations turned on. For the following loop R=(evaluate here); // float N=(evaluate here); // N min=1 max=100...
67
by: S.Tobias | last post by:
I would like to check if I understand the following excerpt correctly: 6.2.5#26 (Types): All pointers to structure types shall have the same representation and alignment requirements as each...
5
by: Gomaw Beoyr | last post by:
Hello Is there any explanation why Microsoft chose to implement arrays as objects allocated on the heap instead of structs allocated on the stack? For "mathematical stuff", one normally...
12
by: Olaf Baeyens | last post by:
I am porting some of my buffer class code for C++ to C#. This C++ class allocates a block of memory using m_pBuffer=new BYTE; But since the class is also used for pointers for funtions that uses...
13
by: aegis | last post by:
The following was mentioned by Eric Sosman from http://groups.google.com/group/comp.lang.c/msg/b696b28f59b9dac4?dmode=source "The alignment requirement for any type T must be a divisor of...
8
by: Cardman | last post by:
I am hopeful that someone can quickly solve my image alignment issue when things are just not going right and where my attempts to solve this alignment issue have all failed. First of all take a...
12
by: Yevgen Muntyan | last post by:
Hey, Consider the following code: #include <stdlib.h> #define MAGIC_NUMBER 64 void *my_malloc (size_t n) { char *result = malloc (n + MAGIC_NUMBER);
15
by: Pengjun Jia | last post by:
HP-UX 11.23, HP aC++ B3910B A.03.63 Here is a samples. bjhp1 /nfs/users/pjia>cat tt.c #include <stdlib.h> int main() { int i =10 ;
4
by: H.K. Kingston-Smith | last post by:
Thanks to everybody who replied to my question on alignment on stack arrays. In a similar vein, what can one say about the alignment of p in char *p = alloca(N) ; where N can be any integer...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

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.