Search code examples
cflex-lexer

Indirection requires pointer when multiplying with flex in C


I've been trying to solve this from the past 3 hours and after solving other problems, I get another problems.

Suppose I have a flex file named "main.c":

%{
#include <stdio.h>
#include <stdint.h>
uint32_t WAV_BPM = 120;
uint64_t WAV_ALLOC = 0;
uint32_t WAV_SAMPLE_RATE = 44100;
#define WAV_BPM_PERIOD (double) 60*WAV_SAMPLE_RATE/WAV_BPM;
%}

%%
"NOTE_1" {WAV_ALLOC += WAV_BPM_PERIOD*4;}
"NOTE_2" {WAV_ALLOC += WAV_BPM_PERIOD*2;}
"NOTE_4" {WAV_ALLOC += WAV_BPM_PERIOD;}
"NOTE_8" {WAV_ALLOC += (uint64_t) WAV_BPM_PERIOD/2.0;}
.        {printf("unknown character %s\n", yytext);}
%%

int main(int argc, char *argv[]){
  return 0;
}

After I tried executing this with flex -o mainlex.c main.c && gcc -lfl mainlex.c, I get an error from gcc:

main.c:11:29: error: indirection requires pointer operand ('int' invalid)
{WAV_ALLOC += WAV_BPM_PERIOD*4;}
                            ^~
...

How did this happen? I'm not dealing with pointers, I'm just multiplying variables. And when I replaced #define WAV_BPM_PERIOD (double) 60*WAV_SAMPLE_RATE/WAV_BPM; todouble WAV_BPM_PERIOD = (double) 60*WAV_SAMPLE_RATE/WAV_BPM;, gcc gives me an another problem:

main.c:7:52: error: initializer element is not a compile-time constant
double WAV_BPM_PERIOD = (double) 60*WAV_SAMPLE_RATE/WAV_BPM;
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~

Solution

  • How did this happen?

    Sloppy macros. You have a stray semicolon so the compiler sees (double) 60*WAV_SAMPLE_RATE/WAV_BPM;*4. A proper macro would have been written as:

    #define WAV_BPM_PERIOD (60.0*WAV_SAMPLE_RATE/WAV_BPM)
    

    error: initializer element is not a compile-time constant

    What it says, the initializer is not a compile-time constant. This is FAQ, you can't initialize file scope variables ("globals") with other variables, since a variable is neither resolved at compile-time, nor an integer constant expression. You could solve this by changing the declaration of WAV_SAMPLE_RATE etc into #define WAV_SAMPLE_RATE 44100 instead of a variable.