Recent Posts

Tags

News

  • A blog about Microsoft Windows development, focused on kernel-mode driver development, the Windows DDK, WDK, and related tools.

    To elaborate on the copyright notice at the bottom: all content produced by me on this site is copyright and licensed as follows:

    <!-- Creative Commons License --> Creative Commons License
    This work is licensed under a Creative Commons License. <!-- /Creative Commons License --> <!-- <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <Work rdf:about=""> <dc:type rdf:resource="http://purl.org/dc/dcmitype/Text" /> <license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0/" /> </Work> <License rdf:about="http://creativecommons.org/licenses/by-nc/2.0/"> <permits rdf:resource="http://web.resource.org/cc/Reproduction" /> <permits rdf:resource="http://web.resource.org/cc/Distribution" /> <requires rdf:resource="http://web.resource.org/cc/Notice" /> <requires rdf:resource="http://web.resource.org/cc/Attribution" /> <prohibits rdf:resource="http://web.resource.org/cc/CommercialUse" /> <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" /> </License> </rdf:RDF> -->

    Although I work for Positive Networks, this work is my own and is not connected with my employer in any way.

    <!-- technorati again --> <script type="text/javascript" src="http://embed.technorati.com/embed/8xz8dihr.js"> </script>

Community

Email Notifications

Other Blogs

General

Technical Resources

About Me

Archives

Kernel Mustard

Reflections on Windows System Programming
Steve Dispensa, MVP - Windows DDK

Pointer Stew, Revisited

Here's my take on Pointer Stew, for those who are curious.

char *c[]={
        "ENTER",
        "NEW",
        "POINT",
        "FIRST"
};

char **cp[]={c+3,c+2,c+1,c};
/*
cp[0] == &c[3] == &"FIRST"
cp[1] == &c[2] == &"POINT"
cp[2] == &c[1] == &"NEW"
cp[3] == &c[0] == &"ENTER"
*/

char ***cpp=cp;
/*
cpp[0] == cp[0] == &c[3] == &"FIRST"
cpp[1] == cp[1] == &c[2] == &"POINT"
cpp[2] == cp[2] == &c[1] == &"NEW"
cpp[3] == cp[3] == &c[0] == &"ENTER"
*/

main()
{
        printf("%s",**++cpp);
/*
RULE: prefix unary operators are all the same precedence and associate right->left
RULE: prefix unary increment returns incremented value to the expression

1)  **++cpp ---> *(*(++cpp))
 - increment cpp.  the new table looks like:
cpp[0] == cp[1] == &c[2] == &"POINT"
cpp[1] == cp[2] == &c[1] == &"NEW"
cpp[2] == cp[3] == &c[0] == &"ENTER"

2)  *(*cpp)
 - dereference cpp: *cpp == cpp[0] == cp[1] == &c[2] == &"POINT"

3) *(&"POINT")
 - dereference a reference, leading to: "POINT"

4) printf("%s", "POINT")
 - output "POINT"
*/

        printf("%s ",*--*++cpp+3);
/*
RULE: prefix unary operators are all the same precedence and associate right->left
RULE: binary addition/subtraction operators bind below prefix unary operators
RULE: binary addition/subtraction on pointer types adds/subtracts the size of the object pointed to

1) (*(--(*(++cpp)))) + 3
 - increment cpp.  the new table looks like:
cpp[0] == cp[2] == &c[1] == &"NEW"
cpp[1] == cp[3] == &c[0] == &"ENTER"

2) (*(--(*cpp))) + 3
 - dereference cpp: *cpp == cpp[0] == cp[2] == &c[1] = &"NEW"

3) (*(--&"NEW")) + 3
 - unary prefix decrement &"NEW", which is sizeof(char*), yielding &"ENTER"
   (ref. c[])
 
4) (*(&"ENTER") + 3
 - dereference a reference --> "ENTER"

5) "ENTER" + 3
 - add 3 to the char* --> "ER"

6) printf("%s ", "ER")
 - output "ER "

*/
        printf("%s",*cpp[-2]+3);
/*
RULE: postfix unary operators ([] in this case) bind tightest of the operators here
RULE: prefix arethmetic operations do the obvious thing
RULE: prefix unary operators bind next 
RULE: binary plus/minus are last of the ones here

1) (*(cpp[-2]) + 3
 - we've bumpted cpp twice so far, so we can safely decrement it back to where it started
 - cpp[-2] == cp[0] == &c[3] == &"FIRST"

2) (*(&"FIRST") + 3
 - dereference reference: --> "FIRST"

3) "FIRST" + 3 --> "ST"

4) printf("%s", "ST")
 - output "ST"

 */

        printf("%s\n",cpp[-1][-1]+1);
/*
RULE: postfix unary operators ([] in this case) bind tightest and associate L->R
RULE: binary plus/minus are least precedent
RULE: array subscripting is done by multiplying the integer by the sizeof the
      array element and adding it to the pointer, followed by applying the
      dereference operator, unless the result is itself an array

1) ((cpp[-1])[-1]) + 1
 - again, we can decrement cpp by one due to previous two increments
 - cpp[-1] == cp[1] == &c[2] == &"POINT"

2) (&"POINT"[-1]) + 1
 - subject to rule #3, we have &"POINT" - sizeof(char*) --> *(&"NEW") (cf c[])

3) (*(&"NEW")) + 1
 - dereference the reference --> "NEW"

4) "NEW" + 1
 - pointier math: add sizeof(char) --> "EW"

5) printf("%s\n", "EW");
 - output: "EW\n"

final output:  "POINT" "ER " "ST" "EW\n" --> "POINTER STEW\n"

NOTE that this clever little thing managed to get the 0-terms right every time;
otherwise, the printf's would have crashed
 */
}
Leave a Comment

(required) 

(required) 

(optional)

(required)