On Fri, Jan 03, 2014 at 04:44:48PM +0800, Bin.Cheng wrote: > >> extern uint32_t __bss_start[]; > >> extern uint32_t __data_start[]; > >> > >> void Reset_Handler(void) > >> { > >> /* Clear .bss section (initialize with zeros) */ > >> for (uint32_t* bss_ptr = __bss_start; bss_ptr != __data_start; ++bss_ptr) > >> { > >> *bss_ptr = 0; > >> } > >> } > > > > I believe this is undefined behavior, so GCC can assume > > bss_ptr != __data_start is true always. You need something like > Sorry for posting the premature question. Since both __bss_start and > __data_start are declared as array, it seems there is no undefined > behavior, the check is between two pointers with same type actually,
I think this has been discussed in some PR, unfortunately I can't find it. If it was < or <=, then it would be obvious undefined behavior, those comparisons can't be performed between different objects, the above is questionable, because you still assume that you get through pointer arithmetics from one object to another one, without dereference pointer arithmetics can be at one past last entry in the array, but whether that is equal to the object object is still quite problematic. > right? So the question remains, why GCC would clear the two lower > bits of " __data_start - __bss_start" then? Am I some stupid mistake? That said, if either of __bss_start of __data_start aren't 32-bit aligned, then it is a clear undefined behavior, the masking of low 2 bits (doesn't happen on x86_64) comes from IVopts computing the end as ((__data_start - __bss_start) + 1) * 4 and the __data_start - __bss_start is exact division by 4, apparently we don't fold that back to just (char *) __data_start - (char *) __bss_start + 4. Jakub