title: How does pointer comparison work in C? Is it ok to compare pointers that don't point to the same array?
body: <p>In K&amp;R (The C Programming Language 2nd Edition) chapter 5 I read the following:</p>
  
  <blockquote>
    <p>First, pointers may be compared under certain circumstances.
     If <code>p</code> and <code>q</code> point to members of the same array, then relations like <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&gt;=</code>, etc. work properly.</p>
  </blockquote>
  
  <p>Which seems to imply that only pointers pointing to the same array can be compared.</p>
  
  <p>However when I tried this code</p>
  
  <pre><code>    char t = 't';
      char *pt = &amp;t;
      char x = 'x';
      char *px = &amp;x;
  
      printf("%d\n", pt &gt; px);
  </code></pre>
  
  <p><code>1</code> is printed to the screen.</p>
  
  <p>First of all, I thought I would get undefined or some type or error, because <code>pt</code> and <code>px</code> aren't pointing to the same array (at least in my understanding). </p>
  
  <p>Also is <code>pt &gt; px</code> because both pointers are pointing to variables stored on the stack, and the stack grows down, so the memory address of <code>t</code> is greater than that of <code>x</code>? Which is why <code>pt &gt; px</code> is true?</p>
  
  <p>I get more confused when malloc is brought in. Also in K&amp;R in chapter 8.7 the following is written:</p>
  
  <blockquote>
    <p>There is still one assumption, however, that pointers to different blocks returned by <code>sbrk</code> can be meaningfully compared. This is not guaranteed by the standard which permits pointer comparisons only within an array. Thus this version of <code>malloc</code> is portable only among machines for which the general pointer comparison is meaningful.</p>
  </blockquote>
  
  <p>I had no issue comparing pointers that pointed to space malloced on the heap to pointers that pointed to stack variables. </p>
  
  <p>For example, the following code worked fine, with <code>1</code> being printed: </p>
  
  <pre><code>    char t = 't';
      char *pt = &amp;t;
      char *px = malloc(10);
      strcpy(px, pt);
      printf("%d\n", pt &gt; px);
  </code></pre>
  
  <p>Based on my experiments with my compiler, I'm being led to think that any pointer can be compared with any other pointer, regardless of where they individually point. Moreover, I think pointer arithmetic between two pointers is fine, no matter where they individually point because the arithmetic is just using the memory addresses the pointers store.</p>
  
  <p>Still, I am confused by what I am reading in K&amp;R. </p>
  
  <p>The reason I'm asking is because my prof. actually made it an exam question. He gave the following code:</p>
  
  <blockquote>
  <pre><code>struct A {
      char *p0;
      char *p1;
  };
  
  int main(int argc, char **argv) {
      char a = 0;
      char *b = "W";
      char c[] = [ 'L', 'O', 'L', 0 ];
  
     struct A p[3];
      p[0].p0 = &amp;a;
      p[1].p0 = b;
      p[2].p0 = c;
  
     for(int i = 0; i &lt; 3; i++) {
          p[i].p1 = malloc(10);
          strcpy(p[i].p1, p[i].p0);
      }
  }
  </code></pre>
    
    <p>What do these evaluate to:</p>
    
    <ol>
    <li><code>p[0].p0 &lt; p[0].p1</code></li>
    <li><code>p[1].p0 &lt; p[1].p1</code></li>
    <li><code>p[2].p0 &lt; p[2].p1</code></li>
    </ol>
  </blockquote>
  
  <p>The answer is <code>0</code>, <code>1</code>, and <code>0</code>.</p>
  
  <p>(My professor does include the disclaimer on the exam that the questions are for a Ubuntu Linux 16.04, 64-bit version programming environment)</p>
  
  <p>(editor's note: if SO allowed more tags, that last part would warrant <a href="/questions/tagged/x86-64" class="post-tag" title="show questions tagged &#39;x86-64&#39;" rel="tag">x86-64</a>, <a href="/questions/tagged/linux" class="post-tag" title="show questions tagged &#39;linux&#39;" rel="tag">linux</a>, and maybe <a href="/questions/tagged/assembly" class="post-tag" title="show questions tagged &#39;assembly&#39;" rel="tag">assembly</a>.  If the point of the question /  class was specifically low-level OS implementation details, rather than portable C.)</p>