A painting of me

Pointers and Arrays

   23 November 2007, mid-afternoon

I’ve been reading up on Ruby in my spare time. I spend most of my time at work writing code in C/C++. The differences between the languages is so stark. Here is a little problem I had at work recently.

In C the relationship between pointers and arrays is so close it is easy to forget that they aren’t quite the same thing. I was creating a list of test cases I wanted a program to run. This is a somewhat simplified example of what I started with; I wanted to loop through the test cases, and run each one.

  1. typedef void (*TestCaseFuncPtr)();
  2.  
  3. TestCaseFuncPtr test_cases [] = { Test1, Test2, NULL }
  4. while (tests)
  5. {
  6. (**tests++)()
  7. }
  8. Download this code: /static/code/13.txt

Now there are two problems here, besides any issues you may have with how obtuse C’s syntax can be or my coding style. First, it won’t compile: the compiler will complain about an invalid lvalue with respect to the code (**tests++)(). Incrementing a pointer is a natural thing to do in C, so why doesn’t this work? Because tests isn’t a pointer its an array: tests is a fixed block of memory large enough to store the three memory addresses listed. To quote K&R, “An array name in not a variable.” If we want traverse the list of test cases in this fashion, we need to use an actual pointer:

  1. typedef void (*TestCaseFuncPtr)();
  2.  
  3. TestCaseFuncPtr test_cases [] = { Test1, Test2, NULL }
  4. TestCaseFuncPtr *curr_test = test_cases;
  5. while (curr_test)
  6. {
  7. (**curr_test++)();
  8. }
  9. Download this code: /static/code/14.txt

This will run, although it will segfault before completing. That’s the second error. Can you figure out what’s wrong? Are these the sorts of questions they ask kids at interviews now, or would this be too simple? (Update: Ryan got it right. The array stores pointers to functions, and we want to know if the address they point to is valid, hence we must dereference before testing. The pointers themselves can’t be NULL, as the space for them to be stored has already been allocated — nevermind testing that they are valid isn’t what we are interested in.)

Mind you, I find Ruby a bizarre and obtuse language in completely different ways. The whole dropping the brackets around function calls trips me out.

|  

Comments

  1. I think for Microsoft and what not they ask you though experiment questions like “How many gas stations are there in Scarborough?”. Not sure if thats a thought experiment or a Fibonacci kind of question.

  2. while ((*curr_test) != NULL)?

Don't be shy, you can comment too!

 
Some things to keep in mind: You can style comments using Textile. In particular, *text* will get turned into text and _text_ will get turned into text. You can post a link using the command "linktext":link, so something like "google":http://www.google.com will get turned in to google. I may erase off-topic comments, or edit poorly formatted comments; I do this very rarely.