Path: csiph.com!eternal-september.org!feeder.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: sizeof on an uninitialized pointer to a VLA Date: Fri, 20 Nov 2015 03:52:15 -0800 Organization: None to speak of Lines: 67 Message-ID: References: <5e03af2c-3c3e-4432-bf5a-000867e5febb@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="945944de09706c9b4e29b53c9d2efdc2"; logging-data="15833"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18R0YOu3LSU/Dku+HnaVoxr" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:tyRbY5FUaldxnGuWQTGsV7QBknc= sha1:k6Snzu4e2oYH+NV5K/M2WOdRWSk= Xref: csiph.com comp.lang.c:76625 James Kuyper writes: > On 11/19/2015 02:39 PM, John Bode wrote: >> I've been using the following idiom a lot to dynamically allocate >> 2D arrays: >> >> T (*arr)[N] = malloc( sizeof *arr * M ); > > M=>N? > >> Works great where N is known at compile time. However, I've also been >> applying it to VLAs, like so: >> >> size_t rows; >> size_t cols; >> ... >> T (*arr)[rows] = malloc( sizeof *arr * cols ); >> >> I've never had any issues, but...does this count as undefined behavior? >> `sizeof` evaluates the operand when it's a VLA, but what does "evaluate" >> mean in this context? Is it trying to dereference the pointer, or is it >> simply determining the size of *any* object the pointer may refer to? > > The key thing about VLA types is that their sized depends upon the value > of one or more expressions, in this case the relevant expression is > "rows". The evaluation it's talking about is the evaluation of that > expression. Unless the expression has side-effects (for example, > rows++), the possibility of it being evaluated is not an issue you need > to worry about. No, the expression `rows` is not evaluated. Consider: size_t rows = 10; char vla[rows]; rows = 20; sizeof vla; `sizeof vla` is 10, not 20. Evaluating `rows` is not just unnecessary; it gives the wrong result. I think the standard is just being sloppy to the point of being incorrect here. For non-VLA types, `sizeof expr` and `sizeof (typename)` are evaluated at compile time. For an expression of a VLA type, `sizeof expr` has to be determined at run time, but the only thing that actually needs to be evaluated is the stored value of whatever anonymous object the compiler uses to remember the size (with perhaps some other computation if, for example, the stored value is an element count). Neither the expression that determined the size (whose value may not be the same) nor the value of the array object (which consists of the values of its elements) actually needs to be evaluated. For `sizeof` applied to a parenthesized VLA type, any expressions that are part of the type name have to be evaluated. For example, in `sizeof (char[func()])`, the function has to be called and any side effects must occur; similarly for `sizeof (char[n++])`. The standard doesn't actually manage to say all this, but I think that's the only reasonable interpretation of the intent. -- 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"