By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,117 Members | 2,142 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,117 IT Pros & Developers. It's quick & easy.

Please explain the output

P: n/a
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";
int *i=(int*)c;
printf("%x", *i);
return 0;
}

The output is:
636261.

I know that hex 61 is decimal 97 which is the ASCII code for a. hex 62
is code for b and so on. My query is why is it printing the ascii codes
in the reverse order.

I apologise if this questios is a very basic one.

Nov 15 '05 #1
Share this Question
Share on Google+
22 Replies


P: n/a
In article <11*********************@g44g2000cwa.googlegroups. com>,
Jaspreet <js***********@gmail.com> wrote:
#include <stdio.h> int main()
{
char *c ="abc";
int *i=(int*)c;
printf("%x", *i);
return 0;
} The output is:
636261.
Not in general, it isn't. For example on the system I'm using,
the output is 61626300
I know that hex 61 is decimal 97 which is the ASCII code for a. hex 62
is code for b and so on. My query is why is it printing the ascii codes
in the reverse order.


On systems in which the representation of integers is little-endian,
the byte order is sometimes 4321 (and sometimes 2143). The order
that an integer (or float or double) is stored into RAM is often
not the same as the internal processor in-register order.
--
"No one has the right to destroy another person's belief by
demanding empirical evidence." -- Ann Landers
Nov 15 '05 #2

P: n/a
Jaspreet wrote:
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";
int *i=(int*)c;
printf("%x", *i);
return 0;
}

The output is:
636261.

I know that hex 61 is decimal 97 which is the ASCII code for a. hex 62
is code for b and so on. My query is why is it printing the ascii codes
in the reverse order.

I apologise if this questios is a very basic one.


In first place, IIRC, this program invokes undefined behaviour because
it dereferences a pointer that has been converted to another type.
Since behaviour is undefined, the output could be anything. For all you
know there could be no output, or your computer may burn.

Besides that, you're probably in a platform with 32 bit integers that
are stored in memory in big endian format. The string "abc" is stored
in memory:

|'a'|'b'|'c'| 0 |
^
|
|
char *c

Now when you cast c to an int* and dereference it, these four bytes are
interpreted as an integer in big endian format, wich means that 0 is
the MSB and 'a' the LSB.

Nov 15 '05 #3

P: n/a
Jaspreet wrote:
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";
It's best to store pointers to string literals in a const pointer to char.
int *i=(int*)c;
This pointer conversion has undefined behaviour; for one thing, the
pointer to char may not be aligned correctly for an int!
printf("%x", *i);
1. the pointer may be mis-aligned
2. if sizeof(int)>4 then part of the value is uninitialised
3. the value may be a trap representation for int
4. the %x specifies an unsigned int, not a signed int
5. the stdout stream should end with a newline character
return 0;
}

The output is:
636261.


That's just one possible result of the undefined behaviour.

--
Simon.
Nov 15 '05 #4

P: n/a

Jaspreet wrote:
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";
int *i=(int*)c;
printf("%x", *i);
return 0;
}

The output is:
636261.


The system who produces this output is a little endian system (x86), if
you run the same code on a big endian system (for example a MC68000
compatible) you will get the output you might expect.

Nov 15 '05 #5

P: n/a
Jaspreet wrote:

I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:
[... program to output *(int *)"abc" in hex ...]
The output is:
636261.

I know that hex 61 is decimal 97 which is the ASCII code for a. hex 62
is code for b and so on. My query is why is it printing the ascii codes
in the reverse order.

I apologise if this questios is a very basic one.


Google for "little endian" and "big endian".

(We're ignoring all of the non-portability issues in the program, of
course.)

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Nov 15 '05 #6

P: n/a
Jaspreet wrote:
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";
int *i=(int*)c;
printf("%x", *i);
return 0;
}

The output is:
636261.

I know that hex 61 is decimal 97 which is the ASCII code for a. hex 62
is code for b and so on. My query is why is it printing the ascii codes
in the reverse order.

I apologise if this questios is a very basic one.


Here's a hint: Big vs little endian.

--
Eric Laberge
Nov 15 '05 #7

P: n/a
Jaspreet wrote on 16/09/05 :
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";
int *i=(int*)c;
Undefined behaviour (UB). There is no guarantee that the address of a
string literal is correctly aligned for a int.
printf("%x", *i);
Undefined behaviour. "%x" expects an unsigned int.

A '\n' is missing (unterminated line). The result may appear or not.
return 0;
}

The output is:
636261.
Once the UB's fixed, the behaviour is implementation-dependent (size of
an int, endianness, charset). The result is target-dependent. It can't
be explainded without knowing the details of the implementation.
I know that hex 61 is decimal 97 which is the ASCII code for a. hex 62
is code for b and so on. My query is why is it printing the ascii codes
in the reverse order.
Try on a Mac...
I apologise if this questios is a very basic one.


This question is idiotic. The interviewer is a idiot. The company that
hires such an idiotic is simply going to die. Try another place.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
Nov 15 '05 #8

P: n/a
In article <11**********************@g47g2000cwa.googlegroups .com>,
Antonio Contreras <an*****@gmail.com> wrote:
In first place, IIRC, this program invokes undefined behaviour because
it dereferences a pointer that has been converted to another type.
Since behaviour is undefined, the output could be anything.
-As written- your statement ignores (char *) access, which -is-
legal (but makes no promises about what you get when you read
out internal padding bytes.)

Besides that, you're probably in a platform with 32 bit integers that
are stored in memory in big endian format. The string "abc" is stored
in memory: |'a'|'b'|'c'| 0 |
^
|
|
char *c Now when you cast c to an int* and dereference it, these four bytes are
interpreted as an integer in big endian format, wich means that 0 is
the MSB and 'a' the LSB.


Just the opposite: "big endian" means that the address is of the
"big end", which is to say the MSB.

The claimed output will occur only for a subset of "little endian" systems.
--
"I will speculate that [...] applications [...] could actually see a
performance boost for most users by going dual-core [...] because it
is running the adware and spyware that [...] are otherwise slowing
down the single CPU that user has today" -- Herb Sutter
Nov 15 '05 #9

P: n/a

Simon Biber wrote:
Jaspreet wrote:
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";


It's best to store pointers to string literals in a const pointer to char.
int *i=(int*)c;


This pointer conversion has undefined behaviour; for one thing, the
pointer to char may not be aligned correctly for an int!


In what regard is it undefined behavior? The conversion will produce an
implementation defined value. Subsequent use by dereferencing it may
invoke undefined behavior though.

--
aegis

Nov 15 '05 #10

P: n/a
aegis wrote:

Simon Biber wrote:
Jaspreet wrote:
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";


It's best to store pointers to string literals
in a const pointer to char.
int *i=(int*)c;


This pointer conversion has undefined behaviour; for one thing, the
pointer to char may not be aligned correctly for an int!


In what regard is it undefined behavior?
The conversion will produce an
implementation defined value.


No.
If the pointer to char, is not aligned correctly for an int,
then you have no assignment.
On systems that do have a requirement for alignment,
you can't just write an int value anywhere that it will fit.
It has to be written on an int alignment boundry.

--
pete
Nov 15 '05 #11

P: n/a

pete wrote:
aegis wrote:

Simon Biber wrote:
Jaspreet wrote:
> I was recently asked this question in an interview. Unfortunately I was
> not able to answer it and the interviewer made a decision on my C
> strengths (or weekness) based on this single question and that was a
> sad end to my interview. Here is the program:
>
> #include <stdio.h>
>
> int main()
> {
> char *c ="abc";

It's best to store pointers to string literals
in a const pointer to char.

> int *i=(int*)c;

This pointer conversion has undefined behaviour; for one thing, the
pointer to char may not be aligned correctly for an int!


In what regard is it undefined behavior?
The conversion will produce an
implementation defined value.


No.
If the pointer to char, is not aligned correctly for an int,
then you have no assignment.
On systems that do have a requirement for alignment,
you can't just write an int value anywhere that it will fit.
It has to be written on an int alignment boundry.


I think you are confusing initialization with 'assignment'.
Also, I don't see how what you are saying follows.
Do you have a chapter and verse?
--
aegis

Nov 15 '05 #12

P: n/a
"aegis" <ae***@mad.scientist.com> writes:
Simon Biber wrote:
Jaspreet wrote:
> I was recently asked this question in an interview. Unfortunately I was
> not able to answer it and the interviewer made a decision on my C
> strengths (or weekness) based on this single question and that was a
> sad end to my interview. Here is the program:
>
> #include <stdio.h>
>
> int main()
> {
> char *c ="abc";


It's best to store pointers to string literals in a const pointer to char.
> int *i=(int*)c;


This pointer conversion has undefined behaviour; for one thing, the
pointer to char may not be aligned correctly for an int!


In what regard is it undefined behavior? The conversion will produce an
implementation defined value. Subsequent use by dereferencing it may
invoke undefined behavior though.


C99 6.3.2.3p7:

A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the
resulting pointer is not correctly aligned for the pointed-to
type, the behavior is undefined.

It's likely, but not required, that the string literal "abc" will
happen to be aligned sufficiently for an int. Even if it isn't, it's
likely that no visible error will occur until and unless you attempt
to dereference the resulting pointer-to-int. But it's still UB.

--
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.
Nov 15 '05 #13

P: n/a
On Fri, 16 Sep 2005 17:23:49 +0000 (UTC), ro******@ibd.nrc-cnrc.gc.ca
(Walter Roberson) wrote in comp.lang.c:
Antonio Contreras <an*****@gmail.com> wrote:
In first place, IIRC, this program invokes undefined behaviour because
it dereferences a pointer that has been converted to another type.
Since behaviour is undefined, the output could be anything.
-As written- your statement ignores (char *) access, which -is-
legal (but makes no promises about what you get when you read
out internal padding bytes.)


You are quite wrong, and you snipped too much context to show it. Here
is the OP's code, replaced:
#include <stdio.h>

int main()
{
char *c ="abc";
int *i=(int*)c;
printf("%x", *i);
return 0;
}


The code is defining a string literal, then assigning the address of
that string literal via a cast to a pointer to int, then dereferencing
the int pointer.

That is undefined behavior pure and simple. Memory that is not an int
is being accessed as an int.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 15 '05 #14

P: n/a
Emmanuel Delahaye wrote:

Jaspreet wrote on 16/09/05 :
I was recently asked this question in an interview. Unfortunately I was [...] char *c ="abc";
int *i=(int*)c; [...] The output is:
636261.


Once the UB's fixed, the behaviour is implementation-dependent (size of
an int, endianness, charset). The result is target-dependent. It can't
be explainded without knowing the details of the implementation.
I know that hex 61 is decimal 97 which is the ASCII code for a. hex 62
is code for b and so on. My query is why is it printing the ascii codes
in the reverse order.


Try on a Mac...
I apologise if this questios is a very basic one.


This question is idiotic. The interviewer is a idiot. The company that
hires such an idiotic is simply going to die. Try another place.


Perhaps the inverviewer was hoping for an answer along the lines of
"because the printer doesn't have a nasal-daemon font"? (Okay, that's
probably not the answer he was looking for.)

I don't know if I'd call the interviewer an "idiot". It may be that
this company writes device drivers for Windows boxes, and isn't really
interested in portability.

I'd have to see the rest of the questions before I'd pass judgement.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Nov 15 '05 #15

P: n/a
Keith Thompson wrote:
[...]
> char *c ="abc"; [...] > int *i=(int*)c;

This pointer conversion has undefined behaviour; for one thing, the
pointer to char may not be aligned correctly for an int!


In what regard is it undefined behavior? The conversion will produce an
implementation defined value. Subsequent use by dereferencing it may
invoke undefined behavior though.


C99 6.3.2.3p7:

A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the
resulting pointer is not correctly aligned for the pointed-to
type, the behavior is undefined.

It's likely, but not required, that the string literal "abc" will
happen to be aligned sufficiently for an int. Even if it isn't, it's
likely that no visible error will occur until and unless you attempt
to dereference the resulting pointer-to-int. But it's still UB.


It only says that "if the resulting pointer is not correctly aligned"
is the behavior undefined. However, if the pointer is aligned, is
the behavior still "undefined", or is it "implementation defined"?

Suppose you had this:

struct foo
{
char str[4];
int i;
}
c = { "abc" };

...

int *i = (int *)c.str;

Doesn't the standard guarantee that the struct be aligned in such a
way that c.str (the first struct element) must be properly aligned for
an int?

Does this still invoke "undefined behavior"?

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Nov 15 '05 #16

P: n/a
"Emmanuel Delahaye" <em***@YOURBRAnoos.fr> writes:
Jaspreet wrote on 16/09/05 :
I was recently asked this question in an interview. Unfortunately I was
not able to answer it and the interviewer made a decision on my C
strengths (or weekness) based on this single question and that was a
sad end to my interview. Here is the program:

#include <stdio.h>

int main()
{
char *c ="abc";
int *i=(int*)c;
printf("%x", *i);
return 0;
}

The output is:
636261.

[...]
This question is idiotic. The interviewer is a idiot. The company that
hires such an idiotic is simply going to die. Try another place.


Not necessarily. Even though the behavior is undefined (nasal demons
and all that), it's not unreasonable to ask for an explanation of why
the program might happen to behave in some particular manner. This
kind of analysis can be important in debugging existing code.

I might even ask that kind of question in an interview myself. The
interviewee most likely to get the job would be the one who gave an
answer something like this:

This is horrible code that should never have been written this
way in the first place. The conversion of c to int* potentially
invokes undefined behavior if the string literal isn't properly
aligned for an int. As far as the C language standard is
concerned, there's nothing more to be said. But ...

If the conversion doesn't blow up, the dereference on the following
line may still do so. Assuming that "works", it assumes that
int is 4 bytes (the size of the string literal including the
trailing '\0'); if int is smaller than 4 bytes it won't grab
the whole string literal, and if int is bigger than 4 bytes it
will access memory beyond the string -- undefined behavior again.
The value of *i depends on the character encoding used and on the
byte ordering used for type int. It's possible, but unlikely,
that the value of *i will be a trap representation; if so, this
is undefined behavior again.

"int main()" is acceptable, but "int main(void)" is better.

"i" is a lousy name for a pointer variable. "c" isn't great
either.

The program should write a newline at the end of its output;
if it doesn't, the output may not appear on some systems.

If the output of the program is "636261", you can *probably*
reach the following conclusions:

The system has 8-bit chars and 32-bit ints.

The string literal happens to be aligned properly to be accessed
as an int. This could mean either than it's 4-byte aligned,
or that the system doesn't require 4-byte alignment for ints.
We could find out which by changing the initialization of i to
"(int*)(c+1) and seeing whether it then blows up.

The system uses an ASCII encoding for characters ('a'==61, 'b'==62,
'c'=63).

The system uses a little-endian representation for integers
(it's likely to be an x86).

If you really want a program that does this (for some reason),
you should shift each byte value into the result. Using memcpy()
would avoid the alignment issue, but not some of the other
portability issues.

If this code occurs in production software, it should be fixed as
soon as possible. Since any bug fix risks introducing new bugs,
the fix will have to go through the full testing cycle before
being released. (You do have a formal testing cycle, right?)
I wouldn't expect an interviewee, especially for an entry-level job,
to pick up on *all* these points, but anyone who can explain
reasonably well both why the code is bad and why it might produce the
observed output is a promising candidate.

Looking at it from the other side, if I were given this question in an
interview, I'd try to cover most of these points (at least until the
interviewer tells me to stop). If this is actually what the
interviewer is looking for, that's a good sign. If he expected me
just to explain why the code produces "636261", assuming that's the
only correct answer, I'm more likely to look elsewhere. On the other
other hand, if he didn't know about the problems with the code but
seems willing to learn, that may be an even better sign.

--
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.
Nov 15 '05 #17

P: n/a
Kenneth Brody <ke******@spamcop.net> writes:
Keith Thompson wrote:
[...]
>> > char *c ="abc"; [...] >> > int *i=(int*)c;
>>
>> This pointer conversion has undefined behaviour; for one thing, the
>> pointer to char may not be aligned correctly for an int!
>
> In what regard is it undefined behavior? The conversion will produce an
> implementation defined value. Subsequent use by dereferencing it may
> invoke undefined behavior though.


C99 6.3.2.3p7:

A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the
resulting pointer is not correctly aligned for the pointed-to
type, the behavior is undefined.

It's likely, but not required, that the string literal "abc" will
happen to be aligned sufficiently for an int. Even if it isn't, it's
likely that no visible error will occur until and unless you attempt
to dereference the resulting pointer-to-int. But it's still UB.


It only says that "if the resulting pointer is not correctly aligned"
is the behavior undefined. However, if the pointer is aligned, is
the behavior still "undefined", or is it "implementation defined"?

Suppose you had this:

struct foo
{
char str[4];
int i;
}
c = { "abc" };

...

int *i = (int *)c.str;

Doesn't the standard guarantee that the struct be aligned in such a
way that c.str (the first struct element) must be properly aligned for
an int?

Does this still invoke "undefined behavior"?


The standard doesn't *directly* guarantee that c.str is correctly
aligned for an int, but it might be indirectly guaranteed. I can't
think of a way for a conforming implementation to avoid aligning c.str
properly for an int. This is only because str happens to be the first
member of the struct, and it needs to allow for arrays of struct foo.
It's cetainly not something I'd want to depend on. If I really wanted
to force alignment, I'd use a union -- or I'd use memcpy() so I didn't
have to worry about alignment at all.

So yes, if c.str is properly aligned for an int, the conversion
(int*)c.str does *not* invoke undefined behavior. But any attempt to
dereference the resulting int* value could invoke UB (if the
reinterpreted value happens to be a trap representation).

--
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.
Nov 15 '05 #18

P: n/a
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
The standard doesn't *directly* guarantee that c.str is correctly
aligned for an int, but it might be indirectly guaranteed. I can't
think of a way for a conforming implementation to avoid aligning c.str
properly for an int. This is only because str happens to be the first
member of the struct, and it needs to allow for arrays of struct foo.
It's cetainly not something I'd want to depend on. If I really wanted
to force alignment, I'd use a union -- or I'd use memcpy() so I didn't
have to worry about alignment at all.


Or, to force aligment, malloc() the space, since malloc() is certain
to use the most restrictive alignment.
--
Oh, to be a Blobel!
Nov 15 '05 #19

P: n/a
Kenneth Brody <ke******@spamcop.net> writes:

[snip]
Suppose you had this:

struct foo
{
char str[4];
int i;
}
c = { "abc" };

...

int *i = (int *)c.str;

Doesn't the standard guarantee that the struct be aligned in such a
way that c.str (the first struct element) must be properly aligned for
an int?


Yes, the alignment requirements for a struct are at least as
restrictive as the alignment requirements for each of the
members of the struct; this implication must hold because
of the guarantees made by malloc(). The alignment of the
first struct element matches the alignment of the struct,
as you point out.
Nov 15 '05 #20

P: n/a
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Kenneth Brody <ke******@spamcop.net> writes:
[snip]
Suppose you had this:

struct foo
{
char str[4];
int i;
}
c = { "abc" };

...

int *i = (int *)c.str;

Doesn't the standard guarantee that the struct be aligned in such a
way that c.str (the first struct element) must be properly aligned for
an int?


Yes, the alignment requirements for a struct are at least as
restrictive as the alignment requirements for each of the
members of the struct; this implication must hold because
of the guarantees made by malloc(). The alignment of the
first struct element matches the alignment of the struct,
as you point out.


I think it's true that the alignment requirements for a struct are at
least as restrictive as the alignment requirements for each of the
members, but this isn't implies by malloc(). A declared object
needn't be as strictly aligned as one allocated by malloc(). The
restriction follows from the requirements that all the members have to
be properly aligned, however the struct object itself was allocated.

--
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.
Nov 15 '05 #21

P: n/a
Keith Thompson <ks***@mib.org> writes:
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Kenneth Brody <ke******@spamcop.net> writes:
[snip]
Suppose you had this:

struct foo
{
char str[4];
int i;
}
c = { "abc" };

...

int *i = (int *)c.str;

Doesn't the standard guarantee that the struct be aligned in such a
way that c.str (the first struct element) must be properly aligned for
an int?


Yes, the alignment requirements for a struct are at least as
restrictive as the alignment requirements for each of the
members of the struct; this implication must hold because
of the guarantees made by malloc(). The alignment of the
first struct element matches the alignment of the struct,
as you point out.


I think it's true that the alignment requirements for a struct are at
least as restrictive as the alignment requirements for each of the
members, but this isn't implies by malloc(). A declared object
needn't be as strictly aligned as one allocated by malloc(). The
restriction follows from the requirements that all the members have to
be properly aligned, however the struct object itself was allocated.


What I said was the implication must hold because of guarantees made
by malloc(), not that the storage needs to be malloc()'ed for the
implication to hold. Consider the following struct:

struct short_int_short {
short a;
int b;
short c;
};

Suppose sizeof(short) == 2 and sizeof(int) == 4, and these numbers are
also the respective alignments. If being able to malloc() the struct
weren't a consideration, this struct (with no internal padding) could
be aligned to an address that is equal to 2 mod 4. But, since we must
be able to use malloc() to allocate the struct, that set of padding
and alignment requirements doesn't work. So it's only because of the
guarantees made by malloc() that the implication follows.
Nov 15 '05 #22

P: n/a
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Keith Thompson <ks***@mib.org> writes:
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
> Kenneth Brody <ke******@spamcop.net> writes:
> [snip]
>> Suppose you had this:
>>
>> struct foo
>> {
>> char str[4];
>> int i;
>> }
>> c = { "abc" };
>>
>> ...
>>
>> int *i = (int *)c.str;
>>
>> Doesn't the standard guarantee that the struct be aligned in such a
>> way that c.str (the first struct element) must be properly aligned for
>> an int?
>
> Yes, the alignment requirements for a struct are at least as
> restrictive as the alignment requirements for each of the
> members of the struct; this implication must hold because
> of the guarantees made by malloc(). The alignment of the
> first struct element matches the alignment of the struct,
> as you point out.


I think it's true that the alignment requirements for a struct are at
least as restrictive as the alignment requirements for each of the
members, but this isn't implies by malloc(). A declared object
needn't be as strictly aligned as one allocated by malloc(). The
restriction follows from the requirements that all the members have to
be properly aligned, however the struct object itself was allocated.


What I said was the implication must hold because of guarantees made
by malloc(), not that the storage needs to be malloc()'ed for the
implication to hold. Consider the following struct:

struct short_int_short {
short a;
int b;
short c;
};

Suppose sizeof(short) == 2 and sizeof(int) == 4, and these numbers are
also the respective alignments. If being able to malloc() the struct
weren't a consideration, this struct (with no internal padding) could
be aligned to an address that is equal to 2 mod 4. But, since we must
be able to use malloc() to allocate the struct, that set of padding
and alignment requirements doesn't work. So it's only because of the
guarantees made by malloc() that the implication follows.


Hmm. I think you're right (but that's no guarantee of anything). I
had actually written something about 2 mod 4 alignment in my previous
followup, but I deleted it before posting.

My thought was that 2 mod 4 alignment is implicitly forbidden by the
requirement to support arrays of structs with no padding between
elements. But as long as the size of the struct is a multiple of 4,
arrays would still work. Assuming sizeof(short)==2, sizeof(int)==4,
and sizeof(struct short_int_short)==8, the elements of an array
of struct short_int_short could be allocated at addresses (shown
in decimal):
1002
1010
1018
1026
...

But since a malloc()ed block of storage has to be aligned for type int
*and* for type struct short_int_short, the alignments of those two
types (and of any two object types) has to be compatible.

It looks like array requrements *don't* forbid 2 mod 4 alignment (I
thought they did), but the malloc() requirements do (I thought they
didn't).

--
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.
Nov 15 '05 #23

This discussion thread is closed

Replies have been disabled for this discussion.