title: Volatile variable in class: "expected unqualified-id before 'volatile'"?
body: <p>I have two <code>static volatile</code> variables defined in my class <code>ADC</code>. The class is written as: (cropped to save space)</p>
  
  <pre><code>#pragma once
  
  #include "../PeriodicProcess/PeriodicProcess.h"
  #include &lt;stdint.h&gt;
  #include &lt;stdlib.h&gt;
  
  class ADC
  {
  private:
      static inline unsigned char SPI_transfer(unsigned char data);
      void read(uint32_t tnow);
  
      static const unsigned char adc_cmd[9];
      static volatile uint32_t _sum[8];
      static volatile uint16_t _count[8];
  
  public:
      ADC();
      void raw();
      void init(PeriodicProcess * scheduler);
      double ch(uint8_t c);
      bool available(const uint8_t *channelNumbers);
      uint32_t ch6(const uint8_t *channelNumbers, double *result);
  };
  </code></pre>
  
  <p>But compiling the project throws me an error in the cpp file at line 10, 29, 39, &amp; 44:</p>
  
  <p>ADC.cpp thus far:</p>
  
  <pre><code>#include "ADC.h"
  extern "C" {
      // AVR LibC Includes
      #include &lt;inttypes.h&gt;
      #include &lt;stdint.h&gt;
      #include &lt;avr/interrupt.h&gt;
  }
  #include "Arduino.h"
  
  const unsigned char ADC::adc_cmd[9] = { 0x87, 0xC7, 0x97, 0xD7, 0xA7, 0xE7, 0xB7, 0xF7, 0x00 };
  
  
  #define bit_set(p,m)   ((p) |= ( 1&lt;&lt;m))
  #define bit_clear(p,m) ((p) &amp;= ~(1&lt;&lt;m))
  
  // We use Serial Port 2 in SPI Mode
  #define ADC_DATAOUT     51    // MOSI
  #define ADC_DATAIN      50    // MISO
  #define ADC_SPICLOCK    52    // SCK
  #define ADC_CHIP_SELECT 33    // PC4   9 // PH6  Puerto:0x08 Bit mask : 0x40
  
  // DO NOT CHANGE FROM 8!!
  #define ADC_ACCEL_FILTER_SIZE 8
  
  #define TCNT2_781_HZ   (256-80)
  #define TCNT2_1008_HZ  (256-62)
  #define TCNT2_1302_HZ  (256-48)
  
  unsigned char ADC::SPI_transfer(unsigned char data)
  {
      // Put data into buffer, sends the data
      UDR2 = data;
      // Wait for data to be received
      while ( !(UCSR2A &amp; (1 &lt;&lt; RXC2)) );
      // Get and return received data from buffer
      return UDR2;
  }
  
  ADC::ADC()
  {
      //Do nothing
  }
  
  void ADC::read(uint32_t tnow)
  {
      uint8_t ch;
  
      bit_clear(PORTC, 4);                            // Enable Chip Select (PIN PC4)
      ADC_SPI_transfer(adc_cmd[0]);                       // Command to read the first channel
  
      for (ch = 0; ch &lt; 8; ch++) {
          uint16_t v;
  
          v = ADC_SPI_transfer(0) &lt;&lt; 8;            // Read first byte
          v |= ADC_SPI_transfer(adc_cmd[ch + 1]);  // Read second byte and send next command
  
          if (v &amp; 0x8007) {
              // this is a 12-bit ADC, shifted by 3 bits.
              // if we get other bits set then the value is
              // bogus and should be ignored
              continue;
          }
  
          if (++_count[ch] == 0) {
              // overflow ... shouldn't happen too often
              // unless we're just not using the
              // channel. Notice that we overflow the count
              // to 1 here, not zero, as otherwise the
              // reader below could get a division by zero
              _sum[ch] = 0;
              _count[ch] = 1;
          }
          _sum[ch] += (v &gt;&gt; 3);
      }
  
      bit_set(PORTC, 4);                  // Disable Chip Select (PIN PC4)
  }
  
  void ADC::init(AP_PeriodicProcess * scheduler)
  {
      pinMode(ADC_CHIP_SELECT, OUTPUT);
  
      digitalWrite(ADC_CHIP_SELECT, HIGH);  // Disable device (Chip select is active low)
  
      // Setup Serial Port2 in SPI mode
      UBRR2 = 0;
      DDRH |= (1 &lt;&lt; PH2); // SPI clock XCK2 (PH2) as output. This enable SPI Master mode
      // Set MSPI mode of operation and SPI data mode 0.
      UCSR2C = (1 &lt;&lt; UMSEL21) | (1 &lt;&lt; UMSEL20); // |(0 &lt;&lt; UCPHA2) | (0 &lt;&lt; UCPOL2);
      // Enable receiver and transmitter.
      UCSR2B = (1 &lt;&lt; RXEN2) | (1 &lt;&lt; TXEN2);
      // Set Baud rate
      UBRR2 = 2;  // SPI clock running at 2.6MHz
  
      // get an initial value for each channel. This ensures
      // _count[] is never zero
      for (uint8_t i=0; i&lt;8; i++) {
          uint16_t adc_tmp;
          adc_tmp  = ADC_SPI_transfer(0) &lt;&lt; 8;
          adc_tmp |= ADC_SPI_transfer(adc_cmd[i + 1]);
          _count[i] = 1;
          _sum[i]   = adc_tmp;
      }
  
      last_ch6_micros = micros();
  
      scheduler-&gt;register_process( AP_ADC_ADS7844::read );
  
  }
  
  // Read one channel value
  double ADC::ch(uint8_t c)
  {
      uint16_t count;
      uint32_t sum;
  
      // Ensure we have at least one value
      while (_count[c] == 0); // Waiting while
  
      // grab the value with interrupts disabled, and clear the count
      cli();
      count = _count[c];
      sum   = _sum[c];
      _count[c] = 0;
      _sum[c]   = 0;
      sei();
  
      return ((double)sum)/count;
  }
  
  // See if Ch6() can return new data
  bool ADC::available(const uint8_t *channelNumbers)
  {
      uint8_t i;
  
      for (i=0; i&lt;6; i++)
      {
          if (_count[channelNumbers[i]] == 0)
          {
              return false;
          }
      }
      return true;
  }
  
  // Read 6 channel values
  // this assumes that the counts for all of the 6 channels are
  // equal. This will only be true if we always consistently access a
  // sensor by either Ch6() or Ch() and never mix them. If you mix them
  // then you will get very strange results
  uint32_t ADC::ch6(const uint8_t *channelNumbers, double *result)
  {
      uint16_t count[6];
      uint32_t sum[6];
      uint8_t i;
  
      // Ensure we have at least one value
      for (i=0; i&lt;6; i++)
      {
          while (_count[channelNumbers[i]] == 0); // Waiting while
      }
  
      // Grab the values with interrupts disabled, and clear the counts
      cli();
      for (i=0; i&lt;6; i++)
      {
          count[i] = _count[channelNumbers[i]];
          sum[i]   = _sum[channelNumbers[i]];
          _count[channelNumbers[i]] = 0;
          _sum[channelNumbers[i]]   = 0;
      }
      sei();
  
      // Calculate averages. We keep this out of the cli region
      // to prevent us stalling the ISR while doing the
      // division. That costs us 36 bytes of stack, but I think its
      // worth it.
      for (i = 0; i &lt; 6; i++)
      {
          result[i] = (sum[i] + count[i]) / (double)count[i];
      }
  
      // Return number of microseconds since last call
      uint32_t us = micros();
      uint32_t ret = us - last_ch6_micros;
      last_ch6_micros = us;
      return ret;
  }
  </code></pre>
  
  <hr>
  
  <p>With the error report providing:</p>
  
  <pre><code>ADC.cpp:10: error: expected unqualified-id before 'volatile'
  ADC.cpp:10: error: expected `)' before 'volatile'
  ADC.cpp:10: error: expected `)' before 'volatile'
  ADC.cpp:29: error: expected unqualified-id before 'volatile'
  ADC.cpp:29: error: expected `)' before 'volatile'
  ADC.cpp:29: error: expected `)' before 'volatile'
  ADC.cpp:39: error: expected unqualified-id before 'volatile'
  ADC.cpp:39: error: expected `)' before 'volatile'
  ADC.cpp:39: error: expected `)' before 'volatile'
  ADC.cpp:44: error: expected unqualified-id before 'volatile'
  ADC.cpp:44: error: expected `)' before 'volatile'
  ADC.cpp:44: error: expected `)' before 'volatile'
  </code></pre>
  
  <p>What is wrong here? Why is it pointing to my constant static defn? Why does it hate 3 of my class methods? Why is it expecting a ')' for a volatile where a volatile does not exist on that line? Why is it <strong>expecting</strong> an <em>unqualified-id</em> (shouldn't that be the other way around)?</p>