TL;DR version
For so few values, any differences in speed will be immeasurably small, and you'd be better off sticking with the more straightforward, easier-to-understand version.  It isn't until you need to start searching through tables containing thousands to millions of entries that you'll want something smarter than a linear ordered search.  
James Michener Version
Another possibility not yet mentioned is to do a partitioned search, like so:
if ( a > 4 )
{
  if ( a > 6 )
  {
    if ( a == 7 ) // do stuff
    else // a == 8, do stuff
  }
  else
  {
    if ( a == 5 ) // do stuff
    else // a == 6, do stuff
  }
}
else
{
  if ( a > 2 )
  {
    if ( a == 3 ) // do stuff
    else // a == 4, do stuff
  }
  else
  {
    if ( a == 1 ) // do stuff
    else // a == 2, do stuff
  }
}
No more than three tests are performed for any value of a.  Of course, no less than three tests are performed for any value of a, either.  On average, it should give better performance than the naive 1-8 search when the majority of inputs are 7, but...  
As with all things performance-related, the rule is measure, don't guess.  Code up different versions, profile them, analyze the results.  For testing against so few values, it's going to be hard to get reliable numbers; you'll need to execute each method thousands of times for a given value just to get a useful non-zero time measurement (it also means that any difference between the methods will be ridiculously small).  
Stuff like this can also be affected by compiler optimization settings. You'll want to build at different optimization levels and re-run your tests.  
Just for giggles, I coded up my own version measuring several different approaches:
- naive- the straightforward test from 1 to 8 in order;
- sevenfirst- check for 7 first, then 1 - 6 and 8;
- eightfirst- check from 8 to 1 in reverse order;
- partitioned- use the partitioned search above;
- switcher- use a- switchstatement instead of- if-else;
I used the following test harness:
int main( void )
{
  size_t counter[9] = {0};
  struct timeval start, end;
  unsigned long total_nsec;
  void (*funcs[])(int, size_t *) = { naive, sevenfirst, eightfirst, partitioned, switcher };
  srand(time(NULL));
  printf("%15s %15s %15s %15s %15s %15s\n", "test #", "naive", "sevenfirst", "eightfirst", "partitioned", "switcher" );
  printf("%15s %15s %15s %15s %15s %15s\n", "------", "-----", "----------", "----------", "-----------", "--------" );
  unsigned long times[5] = {0};
  for ( size_t t = 0; t < 20; t++ )
  {
    printf( "%15zu ", t );
    for ( size_t f = 0; f < 5; f ++ )
    {
      total_nsec = 0;
      for ( size_t i = 0; i < 1000; i++ )
      {
        int a = generate();
        gettimeofday( &start, NULL );
        for ( size_t j = 0; j < 10000; j++ )
          (*funcs[f])( a, counter );
        gettimeofday( &end, NULL );
      }
      total_nsec += end.tv_usec - start.tv_usec;
      printf( "%15lu ", total_nsec );
      times[f] += total_nsec;
      memset( counter, 0, sizeof counter );
    }
    putchar('\n');
  }
  putchar ('\n');
  printf( "%15s ", "average:" );
  for ( size_t i = 0; i < 5; i++ )
    printf( "%15f ", (double) times[i] / 20 );
  putchar ('\n' );
  return 0;
}
The generate function produces random numbers from 1 through 8, weighted so that 7 appears half the time.  I run each method 10000 times per generated value to get measurable times, for 1000 generated values.  
I didn't want the performance difference between the various control structures to get swamped by the // do stuff code, so each case just increments a counter, such as
if ( a == 1 )
  counter[1]++;
This also gave me a way to verify that my number generator was working properly.  
I run through the whole sequence 20 times and average the results.  Even so, the numbers can vary a bit from run to run, so don't trust them too deeply.  If nothing else, they show that changes at this level don't result in huge improvements.  For example:
     test #           naive      sevenfirst      eightfirst     partitioned        switcher
     ------           -----      ----------      ----------     -----------        --------
          0             121             100             118             119             111
          1             110             100             131             120             115
          2             110             100             125             121             111
          3             115             125             117             105             110
          4             120             116             125             110             115
          5             129             100             110             106             116
          6             115             176             105             106             115
          7             111             100             111             106             110
          8             139             100             106             111             116
          9             125             100             136             106             111
         10             106             100             105             106             111
         11             126             112             135             105             115
         12             116             120             135             110             115
         13             120             105             106             111             115
         14             120             105             105             106             110
         15             100             131             106             118             115
         16             106             113             116             111             110
         17             106             105             105             118             111
         18             121             113             103             106             115
         19             130             101             105             105             116
   average:      117.300000      111.100000      115.250000      110.300000      113.150000
Numbers are in microseconds.  The code was built using gcc 4.1.2 with no optimization running on a SLES 10 system1.  
So, running each method 10000 times for 1000 values, averaged over 20 runs, gives a total variation of about 7 μsec.  That's really not worth getting exercised over.  For something that's only searching among 8 distinct values and isn't going to run more than "several times", you're not going to see any measurable improvement in performance regardless of the method used.  Stick with the method that's the easiest to read and understand.  
Now, for searching a table containing several hundreds to thousands to millions of entries, you definitely want to use something smarter than a linear search.
1.  It should go without saying, but the results above are only valid for this code built with this specific compiler and running on this specific system.