c - Is it undefined behaviour to call a function with pointers to different elements of a union as arguments? -


this code prints different values after compiling -o1 , -o2 (both gcc , clang):

#include <stdio.h>  static void check (int *h, long *k) {   *h = 5;   *k = 6;   printf("%d\n", *h); }  union myu {     long l;     int i; };  int main (void) {   union myu u;   check(&u.i, &u.l);   return 0; } 

i think should undefined behavior, because of pointer aliasing, cannot pinpoint part of code forbidden.

it write 1 union element , read other, according defect report #283 allowed. ub when union elements accessed through pointers rather directly?

this question similar accessing c union members via pointers, think 1 never answered.

it took me while realize crux of issue here. dr236 discusses it. issue passing pointers function point overlapping storage; , whether compiler allowed assume such pointers may alias each other or not.

if discussing aliasing of union members simpler. in following code:

u.i = 5; u.l = 6; printf("%d\n", u.i); 

the behaviour undefined because effective type of u long; i.e. storage of u contains value stored long. accessing these bytes via lvalue of type int violates aliasing rules of 6.5p7. text inactive union members having unspecified values not apply (imo); aliasing rules trump that, , text comes play when aliasing rules not violated, example, when accessed via lvalue of character type.

if exchange order of first 2 lines above program well-defined.

however, things seem change when accesses "hidden" behind pointers function.

the dr236 addresses via 2 examples. both examples have check() in post. example 1 mallocs memory , passes h , k both pointing start of block. example 2 has union similar post.

their conclusion example 1 "unresolved", , example 2 ub. however, this excellent blog post points out logic used dr236 in reaching these conclusions inconsistent. (thanks tor klingberg finding this).

the last line of dr236 says:

both programs invoke undefined behavior, calling function f pointers qi , qd have different types designate same region of storage. translator has every right rearrange accesses *qi , *qd usual aliasing rules.

(apparently in contradiction of earlier claim example 1 unresolved).

this quote suggests compiler allowed assume 2 pointers passed function restrict if have different types, cannot find wording in standard effect, or addressing issue of compiler re-ordering accesses through pointers.

it has been suggested aliasing rules allow compiler conclude int * , long * cannot access same memory. however, examples 1 , 2 flatly contradict this.

if pointers had same type, think agree compiler cannot reorder accesses, because might both point same object. compiler has assume pointers not restrict unless declared such.

yet, fail see difference between case, , cases of example 1 , 2.

dr236 says:

common understanding union declaration must visible in translation unit.

which again contradicts claim example 2 ub, because in example 2 of code in same translation unit.

my conclusion: seems me c99 wording indicates compiler should not allowed re-order *h = 5; , *k = 6; in case alias overlapping storage. notwithstanding fact dr236 contradicts c99 wording , not clarify matters. reading *h after should cause undefined behaviour, compiler allowed generate output of 5 or 6 , or else.

in reading, if modify check() *k = 6; *h=5; should well-defined print 5. it'd interesting see whether compiler still else in case, , compiler's rationale if does.


Comments

Popular posts from this blog

PHPMotion implementation - URL based videos (Hosted on separate location) -

javascript - Using Windows Media Player as video fallback for video tag -

c# - Unity IoC Lifetime per HttpRequest for UserStore -