Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It's a pointer to a pointer, just like in C (which, despite its strange square-bracket syntax, Objective-C is based on):</p> <pre><code>char c; char *pc = &amp;c; char **ppc = &amp;pc; char ***pppc = &amp;ppc; </code></pre> <p>and so on, ad infinitum (or until you run out of variable space).</p> <p>It's often used to pass a pointer to a function that must be able to change the pointer itself (such as re-allocating memory for a variable-sized object).</p> <p>=====</p> <p>Following your request for a sample that shows how to use it, here's some code I wrote for another post which illustrates it. It's an <code>appendStr()</code> function which manages its own allocations (you still have to free the final version). Initially you set the string (<code>char *</code>) to NULL and the function itself will allocate space as needed.</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;string.h&gt; void appendToStr (int *sz, char **str, char *app) { char *newstr; int reqsz; /* If no string yet, create it with a bit of space. */ if (*str == NULL) { *sz = strlen (app) + 10; if ((*str = malloc (*sz)) == NULL) { *sz = 0; return; } strcpy (*str, app); return; } </code></pre> <p>&nbsp;</p> <pre><code> /* If not enough room in string, expand it. We could use realloc but I've kept it as malloc/cpy/free to ensure the address changes (for the program output). */ reqsz = strlen (*str) + strlen (app) + 1; if (reqsz &gt; *sz) { *sz = reqsz + 10; if ((newstr = malloc (*sz)) == NULL) { free (*str); *str = NULL; *sz = 0; return; } strcpy (newstr, *str); free (*str); *str = newstr; } /* Append the desired string to the (now) long-enough buffer. */ strcat (*str, app); } </code></pre> <p>&nbsp;</p> <pre><code>static void dump(int sz, char *x) { if (x == NULL) printf ("%8p [%2d] %3d [%s]\n", x, sz, 0, ""); else printf ("%8p [%2d] %3d [%s]\n", x, sz, strlen (x), x); } static char *arr[] = {"Hello.", " My", " name", " is", " Pax", " and"," I", " am", " old."}; int main (void) { int i; char *x = NULL; int sz = 0; printf (" Pointer Size Len Value\n"); printf (" ------- ---- --- -----\n"); dump (sz, x); for (i = 0; i &lt; sizeof (arr) / sizeof (arr[0]); i++) { appendToStr (&amp;sz, &amp;x, arr[i]); dump (sz, x); } } </code></pre> <p>The code outputs the following. You can see how the pointer changes when the currently allocated memory runs out of space for the expanded string (at the comments):</p> <pre><code> Pointer Size Len Value ------- ---- --- ----- # NULL pointer here since we've not yet put anything in. 0x0 [ 0] 0 [] # The first time we put in something, we allocate space (+10 chars). 0x6701b8 [16] 6 [Hello.] 0x6701b8 [16] 9 [Hello. My] 0x6701b8 [16] 14 [Hello. My name] # Adding " is" takes length to 17 so we need more space. 0x6701d0 [28] 17 [Hello. My name is] 0x6701d0 [28] 21 [Hello. My name is Pax] 0x6701d0 [28] 25 [Hello. My name is Pax and] 0x6701d0 [28] 27 [Hello. My name is Pax and I] # Ditto for adding " am". 0x6701f0 [41] 30 [Hello. My name is Pax and I am] 0x6701f0 [41] 35 [Hello. My name is Pax and I am old.] </code></pre> <p>In that case, you pass in <code>**str</code> since you need to be able to change the <code>*str</code> value.</p> <p>=====</p> <p>Or the following, which does an unrolled bubble sort (oh, the shame!) on strings that aren't in an array. It does this by directly exchanging the addresses of the strings.</p> <pre><code>#include &lt;stdio.h&gt; static void sort (char **s1, char **s2, char **s3, char **s4, char **s5) { char *t; if (strcmp (*s1, *s2) &gt; 0) { t = *s1; *s1 = *s2; *s2 = t; } if (strcmp (*s2, *s3) &gt; 0) { t = *s2; *s2 = *s3; *s3 = t; } if (strcmp (*s3, *s4) &gt; 0) { t = *s3; *s3 = *s4; *s4 = t; } if (strcmp (*s4, *s5) &gt; 0) { t = *s4; *s4 = *s5; *s5 = t; } if (strcmp (*s1, *s2) &gt; 0) { t = *s1; *s1 = *s2; *s2 = t; } if (strcmp (*s2, *s3) &gt; 0) { t = *s2; *s2 = *s3; *s3 = t; } if (strcmp (*s3, *s4) &gt; 0) { t = *s3; *s3 = *s4; *s4 = t; } if (strcmp (*s1, *s2) &gt; 0) { t = *s1; *s1 = *s2; *s2 = t; } if (strcmp (*s2, *s3) &gt; 0) { t = *s2; *s2 = *s3; *s3 = t; } if (strcmp (*s1, *s2) &gt; 0) { t = *s1; *s1 = *s2; *s2 = t; } } int main (int argCount, char *argVar[]) { char *a = "77"; char *b = "55"; char *c = "99"; char *d = "88"; char *e = "66"; printf ("Unsorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e); sort (&amp;a,&amp;b,&amp;c,&amp;d,&amp;e); printf (" Sorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e); return 0; } </code></pre> <p>which produces:</p> <pre><code>Unsorted: [77] [55] [99] [88] [66] Sorted: [55] [66] [77] [88] [99] </code></pre> <p>Never mind the implementation of sort, just notice that the variables are passed as <code>char **</code> so that they can be swapped easily. Any real sort would probably be acting on a true array of data rather than individual variables but that's not the point of the example.</p>
 

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