3

I am relatively knew to C and only learning pieces of it to publish a Pebble C/PebbleKitJS app to track buses. So far I have the data being processed on a Node server, and I am getting ready to have the data processed by a JS File. MY one problem however lies within the C Code.

This code process data stored in a Key Dictionary sent from JS and assigns it to a variable for use below. By using #define var 9, I can successfully have the .high value set to 9. But through an int var, it fails and throws the error:initializer element not constant?? .

What does this error mean, and what exactly is the difference between static and constant if i don't define it. apparently static vars don't return anything? Some help would be much appreciated.

UPDATE: The problem still isn't fixed. The following new error message occurs in addition to the initializer one. error: (near initialization for 's_data_points[0].high')

   int key0_buffer; 


  void process_tuple(Tuple *t)
{
    //Get key
    int key = t->key;

    //Get integer value, if present
     int value = t->value->int32;

    //Get string value, if present
    char string_value[32];
    strcpy(string_value, t->value->cstring);

    //Decide what to do
    switch(key) {
        case key_0:
            //Location received
            key0_buffer = value;
            break;
  }



  }

static WeatherAppDataPoint s_data_points[] = {

  {
 .city = "San Diego",
     .description = "surfboard :)",
        .icon = WEATHER_APP_ICON_GENERIC_WEATHER,
        .current = 110,
        .high = key0_buffer,
        .low = 9,
  },   
};
AgentSpyname
  • 105
  • 1
  • 9

2 Answers2

2

Try this instead:

enum { key0_buffer = 9 };
  • C doesn't provide for runtime computations while initializing global variables. (The concept does exist as a C++ feature called "dynamic initialization.")

    The execution model is that it can store all the bytes of global variables in ROM, and then copy any modifiable variables into RAM together with a single memcpy. Assigning one global to another would be more complicated.

  • #define allows you to substitute the text 9, which is a constant expression.

    Many frown upon using text substitutions to avoid variables as primitive, unnecessarily low-level, and potentially inefficient. In this case though, the results should be the same.

  • In C, enum constants have type int, so they are a suitable substitute. You're out of luck for other types, though.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • If `s_data_points` was local would the initializer be permitted? (Haven't used C in a while...) – Jesse Good May 11 '15 at 00:42
  • 1
    @JesseGood That's a little off-topic. I recall that it's not allowed in C89 but I'm not sure whether the modern editions permit it. The question is already using some C99 features. — Ah, checked C11 now and it says "All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals," so I guess it is allowed now. – Potatoswatter May 11 '15 at 00:44
  • Ah right `designated initializers` are a C99 feature. I found the answer `In C90, the initialization of array is invalid, since function calls are not constant expressions. C99 removes this restriction for objects with automatic storage duration and allows any run-time expression to be used in the brace-enclosed initializer for such an object. Objects with static storage duration, regardless of type, still must be initialized with constant expressions in C99.` [reference](http://www.drdobbs.com/the-new-c-declarations-initializations/184401377). So yes, if it was local, it would be permitted. – Jesse Good May 11 '15 at 00:47
  • @Potatoswatter Thanks for your help. Coming from a Ruby on Rails, Python and Javascript the concepts from C like const and static are new to me. Accepted – AgentSpyname May 11 '15 at 01:00
  • Whats funny is that I was close to fixing it myself but I mixed up `int const` with `const int`. – AgentSpyname May 11 '15 at 01:03
  • @AgentSpyname The order of `const` and `int` doesn't matter. – Potatoswatter May 11 '15 at 01:04
  • @Potatoswatter the problem still persists.... even with the definition of `int const` – AgentSpyname May 11 '15 at 01:06
  • @AgentSpyname Very strange… Clang accepts it but GCC doesn't. – Potatoswatter May 11 '15 at 01:15
  • @Potatoswatter I'm using a Cloud IDE called CloudPebble to compile this app... Its only for Pebble watchapps.I'm not sure what compiler it uses. – AgentSpyname May 11 '15 at 01:17
  • @AgentSpyname Almost certainly it's GCC. I've asked: http://stackoverflow.com/questions/30158413/gcc-doesnt-support-simple-integer-constant-expression – Potatoswatter May 11 '15 at 01:21
  • @AgentSpyname Updated. Clang accepts `const` but it's only an extension. Use `enum` instead. – Potatoswatter May 11 '15 at 01:53
  • @Potatoswatter thanks a lot, I'm going to try it out – AgentSpyname May 11 '15 at 03:23
  • I may need to open another question for this, but does this mean i can only use integers and not text? Maybe I should reach out to a member of the Pebble dev team? – AgentSpyname May 11 '15 at 14:12
1

There is a key difference between the code in your function and the code lower down that defines the static variable. The function code is executable -- these lines are going to get run when the function is called.

Your static declaration of WeatherAppDataPoint is just telling the compiler to create the static variable. The initialization values you are placing in that declaration tell the compiler what value to initialize this data to. That is why they must be constant -- these are the values that get loaded in before anything gets executed.

The #define statement just tells the preprocessor to replace all instances of "var" with the string "9". It is literally the same as a cut and paste operation in a text editor. This gets done before the compiler ever sees the code. This is why you have no problems with that; the compiler sees a literal constant, just as if you'd manually typed the "9" directly into the source code.

In 'C', variables don't return things, they store them. Only functions return things. If you want to have an integer declared somewhere, and then assign it to the value of your static variable, that is an actual executable line of code that will need to occur inside of a function somewhere (ie inside of your process_tuple function). The lines of code below the static declaration aren't executed at run time, they just setup the initial state of the program and tell the compiler how big the variable is.

Barry Gackle
  • 829
  • 4
  • 17