home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c      Meh, in C you gotta define EVERYTHING      243,242 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 242,999 of 243,242   
   Tristan Wibberley to bart   
   Re: UB or not UB? was: On Undefined Beha   
   13 Jan 26 21:54:43   
   
   From: tristan.wibberley+netnews2@alumni.manchester.ac.uk   
      
   On 12/01/2026 15:58, bart wrote:   
   >   
   >  struct bar1 {   
   >    union {   
   >      struct {   
   >        int table[4];   
   >        int other_table[4];   
   >       };   
   >      int xtable[8];   
   >    };   
   >  };   
   >   
   >  int foo1(struct bar1* p, int v)   
   >  {   
   >    for (int i = 0; i <= 4; ++i)   
   >      if (p->xtable[i] == v)   
   >        return 1;   
   >    return 0;   
   >  }   
   >   
   > At least your intent is signaled to whomever is reading your code.   
   >   
   > But I don't know if UB goes away, if you intend writing to .table and   
   > .other_table, and reading those values via .xtable (I can't remember the   
   > rules).   
   >   
   > I'm not even sure about there being no padding between .table and   
   > .other_table.   
      
   IIRC indexing a table follows the rules of pointers and doing so outside   
   of a table's bounds is generally U/B except for very peculiar specific   
   cases. You can do it in a struct across members /sometimes/ because a   
   struct is a single object. In general it depends on whether your pointer   
   arithmetic has been written such that it matches the layout of the   
   structure.   
      
   IIRC there is a standard version upon which certain combinations are   
   guaranteed to be packed, the examples above /might/ exemplify some of them.   
      
      
   This is another matter:   
      
   int table[2][4];   
   (table[0][4] == v);   
      
   IIRC, that /is/ a valid reference to the first element of the second   
   table and is easier to rely on than other cases that might be valid.   
      
   ie table[0][4] is equivalent to table[1][0] because both just juggle   
   pointers around within a single object in a way that's a valid pointer   
   at every moment (which is a stronger condition than what's actually   
   required anyway).   
      
   *(*(table + 0) + 4) is /functionally/ equivalent to *(*(table + 1) + 0)   
   and there is validity assured by the way table is defined: table[1] is   
   not a separate object from table[0] and there can be no padding by a   
   peculiarity of the rules even for quite old versions of the standard, I   
   think even C89 but I bet there are others with better memories.   
      
   --   
   Tristan Wibberley   
      
   The message body is Copyright (C) 2026 Tristan Wibberley except   
   citations and quotations noted. All Rights Reserved except that you may,   
   of course, cite it academically giving credit to me, distribute it   
   verbatim as part of a usenet system or its archives, and use it to   
   promote my greatness and general superiority without misrepresentation   
   of my opinions other than my opinion of my greatness and general   
   superiority which you _may_ misrepresent. You definitely MAY NOT train   
   any production AI system with it but you may train experimental AI that   
   will only be used for evaluation of the AI methods it implements.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca