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,977 of 243,242    |
|    bart to Michael S    |
|    Re: UB or not UB? was: On Undefined Beha    |
|    12 Jan 26 15:58:15    |
   
   From: bc@freeuk.com   
      
   On 12/01/2026 14:28, Michael S wrote:   
   > On Thu, 1 Jan 2026 22:54:05 +0100   
      
   > On related note.   
   >   
   >   
   > struct bar1 {   
   > int table[4];   
   > int other_table[4];   
   > };   
   >   
   > struct bar2 {   
   > int other_table[4];   
   > int table[4];   
   > };   
   >   
   > int foo1(struct bar1* p, int v)   
   > {   
   > for (int i = 0; i <= 4; ++i)   
   > if (p->table[i] == v)   
   > return 1;   
   > return 0;   
   > }   
   >   
   >   
   > int foo2(struct bar2* p, int v)   
   > {   
   > for (int i = 0; i <= 4; ++i)   
   > if (p->table[i] == v)   
   > return 1;   
   > return 0;   
   > }   
   >   
   > According to C Standard, access to p->table[4] in foo1() is UB.   
   > [O.T.]   
   > I want to use language (or, better, standardize dialect of C) in which   
   > behavior in this case is defined, but I am bad at influencing other   
   > people. So can not get what I want.   
   > [/O.T.]   
      
      
   So you want to deliberately read one element past the end because you   
   know it will be the first element of other_table?   
      
   I think then it would be better writing it like this:   
      
    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.   
      
   (In my systems language, the behaviour of your original foo1, in an   
   equivalent program, is well-defined. But not of foo2, given that you may   
   read some garbage value beyond the struct, which may or may not be   
   within valid memory.)   
      
      
   > Now the question.   
   > What The Standard says about foo2() ? Is there UB in foo2() as well?   
      
   Given that you may be reading garbage as I said, whether it is UB or not   
   is irrelevant; your program has a bug.   
      
   Unless you can add extra context which would make that reasonable. For   
   example, the struct is within an array, it's not the last element, so it   
   will read the first element of .other_table, and you are doing this   
   knowingly rather than through oversight.   
      
   It might well be UB, but that is a separate problem.   
      
   --- 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