Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I guess this is what I've been trying to avoid, but I finally went and took a look at the <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf" rel="noreferrer">C99 standard</a> myself. Here's what I've found (emphasis added):<br> §6.3.2.2 void </p> <blockquote> <p>1 The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)</p> </blockquote> <p>§6.3.2.3 Pointers </p> <blockquote> <p>1 <strong>A pointer to void may be converted to or from a pointer to any incomplete or object type</strong>. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.</p> </blockquote> <p>And §3.14</p> <blockquote> <p>1 object<br> region of data storage in the execution environment, the contents of which can represent values</p> </blockquote> <p>§6.5</p> <blockquote> <p>An object shall have its stored value accessed only by an lvalue expression that has one of the following types:<br> — <strong>a type compatible with the effective type of the object,</strong><br> — a qualified version of a type compatible with the effective type of the object,<br> — a type that is the signed or unsigned type corresponding to the effective type of the object,<br> — a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,<br> — an aggregate or union type that includes one of the aforementioned types among its<br> members (including, recursively, a member of a subaggregate or contained union), or<br> — a character type.</p> </blockquote> <p>§6.5</p> <blockquote> <p>The effective type of an object for an access to its stored value is the declared type of the<br> object, if any. <strong>If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value</strong>. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.</p> </blockquote> <p>§J.2 Undefined Behavior</p> <blockquote> <p>— An attempt is made to use the value of a void expression, or an implicit or explicit conversion (except to void) is applied to a void expression (6.3.2.2). </p> </blockquote> <h2>Conclusion</h2> <p>It is ok (well-defined) to cast to-and-from a <code>void*</code>, but not ok to use a value of type <code>void</code> in <strong>C99</strong>. Therefore the "real world example" is not undefined behavior. Therefore, the explicit casting method can be used with the following modification, as long as alignment, padding, and byte-order is taken care of:</p> <pre><code>void receive_message(void *bytes, size_t len) { assert(len &gt;= sizeof(struct message); struct message *msg = (struct message*) bytes; /* And now use the message */ if (msg-&gt;command == SELF_DESTRUCT) /* ... */ } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload