Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>For both function and object pointers, they compile but their result is only guaranteed to be consistent for addresses to sub-objects of the same complete object (you may compare the addresses of two members of a class or array) and if you compare a function or object against itself.</p> <p>Using <code>std::less&lt;&gt;</code>, <code>std::greater&lt;&gt;</code> and so on will work with any pointer type, and will give consistent results, even if the result of the respective built-in operator is unspecified:</p> <pre><code>void f() { } void g() { } int main() { int a, b; ///// not guaranteed to pass assert((&amp;a &lt; &amp;b) == (&amp;a &lt; &amp;b)); ///// guaranteed to pass std::less&lt;int*&gt; lss1; assert(lss1(&amp;a, &amp;b) == lss1(&amp;a, &amp;b)); // note: we don't know whether lss1(&amp;a, &amp;b) is true or false. // But it's either always true or always false. ////// guaranteed to pass int c[2]; assert((&amp;c[0] &lt; &amp;c[1]) == (&amp;c[0] &lt; &amp;c[1])); // in addition, the smaller index compares less: assert(&amp;c[0] &lt; &amp;c[1]); ///// not guaranteed to pass assert((&amp;f &lt; &amp;g) == (&amp;f &lt; &amp;g)); ///// guaranteed to pass assert((&amp;g &lt; &amp;g) == (&amp;g &lt; &amp;g)); // in addition, a function compares not less against itself. assert(!(&amp;g &lt; &amp;g)); ///// guaranteed to pass std::less&lt;void(*)()&gt; lss2; assert(lss2(&amp;f, &amp;g) == lss2(&amp;f, &amp;g)); // note: same, we don't know whether lss2(&amp;f, &amp;g) is true or false. ///// guaranteed to pass struct test { int a; // no "access:" thing may be between these! int b; int c[1]; // likewise here int d[1]; test() { assert((&amp;a &lt; &amp;b) == (&amp;a &lt; &amp;b)); assert((&amp;c[0] &lt; &amp;d[0]) == (&amp;c[0] &lt; &amp;d[0])); // in addition, the previous member compares less: assert((&amp;a &lt; &amp;b) &amp;&amp; (&amp;c[0] &lt; &amp;d[0])); } } t; } </code></pre> <p>Everything of that should compile though (although the compiler is free to warn about any code snippet it wants).</p> <hr> <p>Since function types have no <code>sizeof</code> value, operations that are defined in terms of <code>sizeof</code> of the pointee type will not work, these include:</p> <pre><code>void(*p)() = ...; // all won't work, since `sizeof (void())` won't work. // GCC has an extension that treats it as 1 byte, though. p++; p--; p + n; p - n; </code></pre> <p>The unary <code>+</code> works on any pointer type, and will just return the value of it, there is nothing special about it for function pointers. </p> <pre><code>+ p; // works. the result is the address stored in p. </code></pre> <p>Finally note that a pointer to a function <em>pointer</em> is not a function pointer anymore:</p> <pre><code>void (**pp)() = &amp;p; // all do work, because `sizeof (void(*)())` is defined. pp++; pp--; pp + n; pp - n; </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