How to make local variable's address is 8 byte alignment?

P

Pengjun Jia

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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

bjhp1 /nfs/users/pjia>aCC +DD64 tt.c

bjhp1 /nfs/users/pjia>./a.out
800003ffbfff0f78, 800003ffbfff0f7c

I hope the pointer p's address is 800003ffbfff0f80, not
800003ffbfff0f7c
Is there any option to realize this?
 
M

Mark Bluemel

Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

bjhp1 /nfs/users/pjia>aCC +DD64 tt.c

bjhp1 /nfs/users/pjia>./a.out
800003ffbfff0f78, 800003ffbfff0f7c

I hope the pointer p's address is 800003ffbfff0f80, not
800003ffbfff0f7c

Why is this important to you?
Is there any option to realize this?

This is specific to your platform, I'd think, so asking in a
platform-specific group would be more appropriate.

In general, I think you'd need to try playing tricks with embedding "p"
in a union (or possibly a structure) to force alignment.

For example, you may find that something like :-

union {
double for_alignment;
char p[1024];
} fudge.

Would get aligned at an 8-byte boundary.

But I repeat this is platform-specific, so YMMV...
 
P

pete

Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

bjhp1 /nfs/users/pjia>aCC +DD64 tt.c

bjhp1 /nfs/users/pjia>./a.out
800003ffbfff0f78, 800003ffbfff0f7c

I hope the pointer p's address is 800003ffbfff0f80, not
800003ffbfff0f7c
Is there any option to realize this?

/* BEGIN eight_bytes.c */

#include <stdio.h>

#define BYTES 8
#define NUM 256

int main(void)
{
int i[NUM + BYTES / sizeof(int)] = {10};
char *p = BYTES + (char *)i ;

printf("%p, %p\n", (void *)i, (void *)p) ;
return 0 ;
}

/* END eight_bytes.c */
 
F

Flash Gordon

pete wrote, On 10/01/08 11:42:
Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

bjhp1 /nfs/users/pjia>aCC +DD64 tt.c

bjhp1 /nfs/users/pjia>./a.out
800003ffbfff0f78, 800003ffbfff0f7c

I hope the pointer p's address is 800003ffbfff0f80, not
800003ffbfff0f7c
Is there any option to realize this?

/* BEGIN eight_bytes.c */

#include <stdio.h>

#define BYTES 8
#define NUM 256

int main(void)
{
int i[NUM + BYTES / sizeof(int)] = {10};

You have change the type of i which is likely to be a problem. You have
also failed to note that this may well *not* do what is wanted as the C
language does not guarantee how things will be arranged in memory. For
instance some compiler start playing clever tricks with where arrays are
placed on the stack and/or put "guard values" either side of arrays to
detect buffer overflows and/or try and detect when they have occurred.
char *p = BYTES + (char *)i ;

printf("%p, %p\n", (void *)i, (void *)p) ;

It would have been helpful if you had told the OP why you added the
casts. The reason being that %p specifically requires a void* pointer
and other pointer types can have different sizes, representations or
passing mechanisms.
 
D

David Mathog

Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

Well, you could always allocate an extra 8 bytes for the array p
and then use a pointer to the first position in that array which is on
an 8 byte alignment instead of p itself.

I don't see the point though for this example. With integers and such
it will likely make a difference if the variable is not properly
aligned, but the compiler will generally take care of that for you.

Regards,

David Mathog
 
M

Mark Bluemel

David said:
Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

Well, you could always allocate an extra 8 bytes for the array p
and then use a pointer to the first position in that array which is on
an 8 byte alignment instead of p itself.

I don't see the point though for this example. With integers and such
it will likely make a difference if the variable is not properly
aligned, but the compiler will generally take care of that for you.

If the OP wanted to use a general area of bytes as a place he could take
a pointer into and manipulate as (for example) long or double, he may
need this sort of guarantee. Perhaps he'll tell us what he's trying to
do...
 
M

Mark Bluemel

Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

bjhp1 /nfs/users/pjia>aCC +DD64 tt.c

bjhp1 /nfs/users/pjia>./a.out
800003ffbfff0f78, 800003ffbfff0f7c

I hope the pointer p's address is 800003ffbfff0f80, not
800003ffbfff0f7c
Is there any option to realize this?

Of course, the other approach is to malloc the space rather than using
automatic storage, as malloc() must return a block of memory
appropriately aligned for any kind of data, which implies the strictest
alignment constraint.
 
P

pete

Flash said:
pete wrote, On 10/01/08 11:42:
Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

bjhp1 /nfs/users/pjia>aCC +DD64 tt.c

bjhp1 /nfs/users/pjia>./a.out
800003ffbfff0f78, 800003ffbfff0f7c

I hope the pointer p's address is 800003ffbfff0f80, not
800003ffbfff0f7c
Is there any option to realize this?

/* BEGIN eight_bytes.c */

#include <stdio.h>

#define BYTES 8
#define NUM 256

int main(void)
{
int i[NUM + BYTES / sizeof(int)] = {10};

You have change the type of i which is likely to be a problem.
Yes.

You have also failed to note that this may well *not* do what is
wanted as the C language does not guarantee how things will be
arranged in memory.
For instance some compiler start playing clever tricks with
where arrays are
placed on the stack and/or put "guard values" either side of arrays to
detect buffer overflows and/or try and detect when they have occurred.
char *p = BYTES + (char *)i ;

The C language guarantees this much for this case:
1 p is 8 bytes after i
2 p[0] through p[256 * sizeof(int) - 1] may be accessed

This line would have been better though:

int i[(1024 + BYTES) / sizeof(int)] = {10};

then it would have been p[0] through p[1023].
 
J

Jack Klein

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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

bjhp1 /nfs/users/pjia>aCC +DD64 tt.c

bjhp1 /nfs/users/pjia>./a.out
800003ffbfff0f78, 800003ffbfff0f7c

I hope the pointer p's address is 800003ffbfff0f80, not
800003ffbfff0f7c
Is there any option to realize this?

There is no valid or invalid option to align the "pointer p's address"
because 'p' is not, and never will be,a pointer.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
J

Jack Klein

David said:
Pengjun said:
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 ;
char p[1024] ="" ;

printf("%p, %p\n", &i, p) ;
return 0 ;
}

Well, you could always allocate an extra 8 bytes for the array p
and then use a pointer to the first position in that array which is on
an 8 byte alignment instead of p itself.

I don't see the point though for this example. With integers and such
it will likely make a difference if the variable is not properly
aligned, but the compiler will generally take care of that for you.

If the OP wanted to use a general area of bytes as a place he could take
a pointer into and manipulate as (for example) long or double, he may
need this sort of guarantee. Perhaps he'll tell us what he's trying to
do...

No, he can't want to do that, it would produce undefined behavior.
Look up "declared type" in the standard. Since 'p' is defined as an
array of char, accessing it as objects type double or long is
undefined.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
P

Pengjun Jia

Yes, you are right. In later code I have a sentence like this : if
(*((long *) p) == 10000) ; { ... }
So I have to make sure p is 4 alignment (32-bit) and 8 alignment (64-
bit).
 
M

Mark Bluemel

Pengjun Jia wrote: (Top-posting corrected
Yes, you are right. In later code I have a sentence like this : if
(*((long *) p) == 10000) ; { ... }
So I have to make sure p is 4 alignment (32-bit) and 8 alignment (64-
bit).

I thought that must be it.

As I've already said, you need to either
a) use malloc() to get your memory
(that is guaranteed to be correctly aligned and usable for any
data type)
or
b) use a union to force alignment.
(I'm not convinced that this is actually guaranteed to work by
the standard, but in practice, I'm sure it will on most "normal"
hosted C implementations.)
 
J

James Kuyper

Mark said:
Pengjun Jia wrote: (Top-posting corrected .... ....
b) use a union to force alignment.
(I'm not convinced that this is actually guaranteed to work by
the standard, but in practice, I'm sure it will on most "normal"
hosted C implementations.)

How could an implementation of C meet the requirements for how unions
work if one of the union members was misaligned for its type?
 
M

Mark Bluemel

James said:
How could an implementation of C meet the requirements for how unions
work if one of the union members was misaligned for its type?

My concern is whether Jack Klein's comment "Since 'p' is defined as
an array of char, accessing it as objects type double or long is
undefined" was justified...

In Pengjun's position, I'd be using malloc(), I think.
 
J

James Kuyper

Mark said:
My concern is whether Jack Klein's comment "Since 'p' is defined as
an array of char, accessing it as objects type double or long is
undefined" was justified...

I presumed that you were referring to replacing p with a object of a
union type that contained both double and long members. That avoids the
problem that Jack Klein was talking about, at least if the union is used
correctly: never read from a member of one type if the last write was to
a member of the other type.
 
P

pete

Mark said:
Pengjun Jia wrote: (Top-posting corrected


I thought that must be it.

As I've already said, you need to either
a) use malloc() to get your memory
(that is guaranteed to be correctly aligned and usable for any
data type)
or
b) use a union to force alignment.
(I'm not convinced that this is actually guaranteed to work by
the standard, but in practice, I'm sure it will on most "normal"
hosted C implementations.)

The simplest way to acheive alignment and sufficient memory,
is to declare the whole array as being an array of type long,
and then point p, which is a (char *), at one of the members.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top