qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 2/3] hw/virtio-net.c: set config size using host


From: Laszlo Ersek
Subject: Re: [Qemu-devel] [PATCH 2/3] hw/virtio-net.c: set config size using host features
Date: Thu, 07 Feb 2013 16:30:32 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130108 Thunderbird/10.0.12

On 02/07/13 15:43, Laszlo Ersek wrote:
> On 02/07/13 09:55, Michael S. Tsirkin wrote:
>> On Tue, Feb 05, 2013 at 05:47:16PM -0600, Jesse Larrew wrote:

>>> +#define endof(container, field) \
>>> +    ((intptr_t)(&(((container *)0)->field)+1))
>>

> Furthermore, taking the pointer to "one past" &field, ie. (&field + 1),
> is safe, provided &field itself is well-defined. This comes from two
> bits in the ISO C standard, sloppily paraphrased:
> 
> - Given an array with N elements, it's allowed to form a pointer to one
> past the last element in it. IOW, &array[N], or (array + N), or
> (&array[0] + N). You can't dereference it, but the pointer itself is
> valid. (C99 6.5.6p8-9.)
> 
> - For the purposes of pointer arithmetic, (&x) works like (&x_array[0]),
> where x is an object of type X, outside of an array, and x_array has
> element type X and N=1 element. (C99 6.5.6p7.)
> 
> Since you're allowed to evaluate ((&x_array[0]) + 1), you're also
> allowed to eval ((&x) + 1).

Alas, I was wrong; C99 6.5.6p7 doesn't seem to apply here on a second
read, because "x", ie. ((container *)0)->field, is not an existent
object here.

> Anyway the above expression could be reworked for more portability with
> offsetof and sizeof. As-is, it contains a pointer-to-non-void to
> intptr_t conversion; what's more, with the resultant integer value meant
> to be used numerically later on (ie. not for converting it back to
> (void*), C99 7.18.1.4p). (The use of the null pointer is valid, the
> dereference is not evaluated because it's the operand of &, C99
> 6.5.2.3p4 and 6.5.3.2p3.)

Again, I was too liberal here wrt. the null pointer; the operand of &,
((container*)0)->field, is neither the result of the unary * operator,
nor is it "an lvalue that designates an object that [...]". (C99 6.5.3.2p1.)

((container*)0)->field is not an object.

> Instead, what about
> 
> #define endof(container, field) \
>     (offsetof(container, field) + sizeof ((container *)0)->field)

This works nonetheless, because the operand of sizeof is an expression
with a non-VLA type, and so it's not evaluated. (C99 6.5.3.4p2.)

Sorry for the noise.

Laszlo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]