![]() |
| | #1 |
| Registered User Join Date: Jan 2009
Posts: 7
| Problem with compiling code with option -O2 Code: #include <stdio.h>
typedef union {
short s[2];
int i[1];
}foo;
int main()
{
foo f;
short *a = f.s;
int cnt = 0x22222222;;
f.s[0]=0x1111;
f.s[1]=0x1111;
printf("%x %x\n", a[0], a[1]);
printf("%x %x\n", f.s[0], f.s[1]);
printf("\n");
*f.i = cnt;
printf("%x %x\n", a[0], a[1]);
printf("%x %x\n", f.s[0], f.s[1]);
printf("\n");
printf("%x %x\n", a[0], a[1]);
printf("%x %x\n", f.s[0], f.s[1]);
printf("\n");
return 0;
}
1111 1111 1111 1111 2222 2222 2222 2222 2222 2222 2222 2222 But when I used options -O2, I got the next result: 1111 1111 1111 1111 1111 1111 2222 2222 2222 2222 2222 2222 Could you explain where is the problem in the code? Thanks for your help. |
| koushikyou is offline | |
| | #2 |
| Beginner Join Date: Jan 2008 Location: Fujian, China
Posts: 23
| 1111 1111 1111 1111 2222 1111 2222 2222 2222 2222 2222 2222 Gcc 3.4.5 if -O2 is turned on |
| leiming is offline | |
| | #3 |
| Beginner Join Date: Jan 2008 Location: Fujian, China
Posts: 23
| I have come up with an idea, is it because that a is only a pointer to 2 bytes so the compiler doesn't think it has effect beyond the 2 bytes to assign a value to pointer a |
| leiming is offline | |
| | #4 |
| Registered User Join Date: Apr 2006
Posts: 1,309
| Looks like the compiler deduces that "*f.i = cnt;" and "a[0], a[1]" cannot access the same memory location, so it does puts a[0] and a[1] on the stack (in order to pass it to printf) prior or at the same time as modifying "*f.i". This is technically allowed, because accessing the member of a union as a short after assigning to the int version to is undefined behavior. I surprised the compiler makes such a determination, however.
__________________ It is too clear and so it is hard to see. A dunce once searched for fire with a lighted lantern. Had he known what fire was, He could have cooked his rice much sooner. |
| King Mir is offline | |
| | #5 |
| Registered User Join Date: Apr 2008
Posts: 282
| compiling with -fno-strict-aliasing -O2 produces the correct result (or so it seems). The wrong part is to declare i as a pointer (or an array, nevermind), because the compiler assumes it is not an alias to s, replacing int i[1]; by int i; in the union, and *f.i=0x2..2 by f.i=0x2..2 produces the correct result with -O2 and no additional option (because the compiler knows s and i are related). Last edited by root4; 01-07-2009 at 02:32 AM. |
| root4 is offline | |
| | #6 |
| Registered User Join Date: Jan 2009
Posts: 7
| Thank you for your comment. Actually, this sample is modified from the next code: Code: #include <stdio.h>
int main()
{
volatile short a[2];
int cnt = 0x22222222;
a[0]=0x1111;
a[1]=0x1111;
printf("%x %x\n", a[0], a[1]);
*(int *)a = (int)cnt; /* violation of aliasing rules */
printf("%x %x\n", a[0], a[1]);
printf("%x %x\n", a[0], a[1]);
return 0;
}
Some information from google may be helpful. https://www.securecoding.cert.org/co...ompatible+type Any helpful comment is welcome. |
| koushikyou is offline | |
| | #7 |
| Registered User Join Date: Apr 2008
Posts: 282
| The page you linked provide a solution (the one you tried in your first post, except member i is not an array) and it works. Your last problem occurs when casting a pointer to a (non-compatible) type (an array of 2 shorts in not necessarily equivalent to an int, it depends on the implementation type size [the standard only says an int and a short have to be at least 16 bits long]). Plus in your case, indianness may also be an issue. |
| root4 is offline | |
| | #8 | |
| Registered User Join Date: Jan 2009
Posts: 7
| Thank you for your comment. But I want to ask some further question. Quote:
| |
| koushikyou is offline | |
| | #9 | |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| Quote:
-- Mats
__________________ Compilers can produce warnings - make the compiler programmers happy: Use them! Please don't PM me for help - and no, I don't do help over instant messengers. | |
| matsp is offline | |
| | #10 | |
| Registered User Join Date: Jan 2009
Posts: 7
| Quote:
Code: #include <stdio.h>
typedef union {
short s[2];
int i;
}foo;
int main()
{
foo f;
short *a = f.s;
int * b = &f.i;
int cnt = 0x22222222;;
f.s[0]=0x1111;
f.s[1]=0x1111;
printf("%x %x\n", a[0], a[1]);
printf("%x %x\n", f.s[0], f.s[1]);
printf("\n");
// f.i = cnt;
*b = cnt;
printf("%x %x\n", a[0], a[1]);
printf("%x %x\n", f.s[0], f.s[1]);
printf("\n");
printf("%x %x\n", a[0], a[1]);
printf("%x %x\n", f.s[0], f.s[1]);
printf("\n");
return 0;
}
1111 1111 1111 1111 1111 1111 2222 2222 2222 2222 2222 2222 | |
| koushikyou is offline | |
| | #11 |
| Registered User Join Date: Apr 2008
Posts: 282
| After a quick test, simply replacing "*f.i=..." by "f.i[0]=..." seems enough to tell the optimizer 'i' is an alias for 's'. Using 'i' as a pointer, knowing it is of a different type of 's' and using strict aliasing makes the optimizer thinks they are unrelated objects. So in fact, you don't even have to modify your union, ignore my comment about that. |
| root4 is offline | |
| | #12 |
| Registered User Join Date: Jan 2009
Posts: 7
| |
| koushikyou is offline | |
| | #13 |
| Registered User Join Date: Apr 2008
Posts: 282
| Yes, replace all occurences of 's' in what I told, by 'a'... To sum up (how I see things, but I'm not expert on the topic): 's' and 'i' are aliases by default, 'a' is an alias of 's' when initialized, then 'i' is modified, it is accessed as a pointer and its type is _different_ of 'a', so the optimizer (strict aliasing) assumes those objects are no longer related, and applies its optimization (as details by King Mir probably). Same thing with the last example 'b'. Last edited by root4; 01-07-2009 at 03:40 AM. |
| root4 is offline | |
| | #14 |
| Registered User Join Date: Jan 2009
Posts: 7
| Is it a bad coding style or bug of gcc? |
| koushikyou is offline | |
| | #15 |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| Depends on how you look at it - you are aliasing pointers, and gcc -O2 assumes "pointers do not alias" - if you want to avoid that, you should turn of that particular optimization step for the relevant code with -fno-strict-aliasing But it is at the very least bad coding style to do this - even if it's technically not in itself incorrect and the C standard does certainly not forbid pointer aliases. -- Mats
__________________ Compilers can produce warnings - make the compiler programmers happy: Use them! Please don't PM me for help - and no, I don't do help over instant messengers. |
| matsp is offline | |
![]() |
| Tags |
| c o2 aliasing |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Problem Compiling | Flakster | C++ Programming | 4 | 06-13-2006 01:09 AM |
| Help on compiling code | mattyp1977 | C++ Programming | 4 | 03-26-2006 05:07 PM |
| Problem : Threads WILL NOT DIE!! | hanhao | C++ Programming | 2 | 04-16-2004 01:37 PM |
| Request for comments | Prelude | A Brief History of Cprogramming.com | 15 | 01-02-2004 10:33 AM |
| Big Code, Little Problem | CodeMonkey | Windows Programming | 4 | 10-03-2001 05:14 PM |