Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Help on this typedef Date: Fri, 19 May 2017 09:34:04 -0700 Organization: None to speak of Lines: 81 Message-ID: References: <8ad1e08b-bdf9-4baa-a8b4-63bf48fb3e3d@googlegroups.com> <7828b0dd-de46-40a2-9636-81117d1f17f6@googlegroups.com> <799899ab-ccf3-49a4-a928-d405dc142fff@googlegroups.com> <1c41ec70-5868-4a28-a724-58f4bb70e593@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="189d31b8aa2df37c9a5da9ba095e96a2"; logging-data="14760"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+oL4J6MP25BhPO4f5cichK" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:a6WLrJJ3kE5WzQQhmAdz4u9S+iw= sha1:yoVXVf6w9BrFp4a0EK76oIFbxxA= Xref: csiph.com comp.lang.c:110384 joel.rees@gmail.com writes: > On Friday, May 19, 2017 at 1:35:33 AM UTC+9, Keith Thompson wrote: >> joel.rees@somewhere writes: >> > On Monday, May 15, 2017 at 11:23:23 PM UTC+9, Tim Rentsch wrote: >> [...] >> >> Ah. In that case I must demur regarding part of your later >> >> statement. An access through an array type of extent 1 is >> >> not definedly allowed to access elements after the element >> >> at index 0. >> > >> > typedef string_header_s struct >> > { short length; /* limited length */ >> > char text[ 1 ]; >> > } string_header_t; >> >> That's called the "struct hack", and it was always of questionable >> validity. You can likely get away with allocating extra memory and >> referring to, for example, obj.text[10], but the behavior is undefined. > > You don't believe in reading before you spout, I take it. I do believe in it, though I don't always succeed. I have occasionally made the mistake of posting without reading and understanding an entire article, and when I do that I appreciate having it pointed out. > Go back, read the source you clipped and tell me that again. Ok, I've re-read your previous article and I'll tell you that again. The behavior is undefined. Here's a demo program, based on your declaration above with the syntax error corrected: #include #include #include int main(void) { typedef struct string_header_s { short length; /* limited length */ char text[ 1 ]; } string_header_t; string_header_t *p = malloc(sizeof *p + 10); /* more than we need */ if (p == NULL) exit(EXIT_FAILURE); p->length = 4; strcpy(p->text, "abcd"); printf("p->text[3] = '%c'\n", p->text[3]); } When I compile and run this on my system, I get no compile-time diagnostics and the output, as expected, is: p->text[3] = 'd' But both the strcpy() call and the reference to p->text[3] have undefined behavior. Concentrating on the latter, the indexing operator [] is defined in terms of pointer addition, in this case (p->text + 3). The description of pointer addition, in N1570 6.5.6p8, says: If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. The array object in question is p->text, which is of type char[1]. We've used malloc to allocate additional memory past the end of that array object, but it's not part of the array object. Most, perhaps all, C compilers will accept this and generate code that behaves as expected, precisely because the struct hack is a common idiom. Nevertheless, the behavior is not defined by the standard. If you disagree, I'm paying attention. -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"