2

I know there is a C++ version of this question, however I'm using standard typedefs not templates.

I've written a program that works with 16-bit wav files. It does this by loading each sample into a short. The program then performs arithmetic on the short.

I'm now modifying the program so it can with with both 16- and 32-bit wavs. I was hoping to do a conditional typedef, i.e. using short for 16-bit and int for 32-bit. But then I realised that the compiler probably would not compile the code if it did not know what the type of a variable is beforehand.

So I tried to test out the following code:

#include <stdio.h>

int
main()
{
  int i;
  scanf("%i", &i);

  typedef short test;

  if(i == 1)
    typedef short sample;
  else 
    typedef int sample;

  return 0;
}

And got got the following compiler errors:

dt.c: In function ‘main’:
dt.c:12:5: error: expected expression before ‘typedef’
dt.c:14:5: error: expected expression before ‘typedef’

Does this mean that runtime conditional typedefs in C are not possible?

[Open-ended question:] If not, how would you guys handle something like this?

rhlee
  • 3,857
  • 5
  • 33
  • 38
  • 3
    Yes, runtime typedefs are impossible. The compiler needs to allocate storage for `sample s;`, for that it must know the size. – Daniel Fischer Jul 18 '12 at 12:25
  • Consider using `` (and/or ``) and `uint16_t` and `int32_t` etc. This is from C99, of course, but even retrograde compilers usually provide the facility (or can be provided with the headers). – Jonathan Leffler Jul 18 '12 at 13:11

5 Answers5

5

typedef is a compiler feature, you cannot apply it on runtime.

MByD
  • 135,866
  • 28
  • 264
  • 277
4

All types in a program must be known at compile time.

In C++ you could compile your code for short and int using templates; in C you can do this using macros (specifically, X-macros).

Put your calculation code in a separate file called e.g. dt.tmpl.c, then in dt.c write:

#define sample int
#include "dt.tmpl.c"

#define sample short
#include "dt.tmpl.c"

Your dt.tmpl.c code can then use sample as a preprocessor token to name types and paste into function names, for example:

#define PASTE(name, type) name ## _ ## type
#define FUNCTION_NAME(name, type) PASTE(name, type)

sample FUNCTION_NAME(my_calculation, sample)(sample i) {
    return i * 2;
}

This will result in two functions int my_calculation_int(int i) and short my_calculation_short(short i) which you can then use elsewhere.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • You can only paste in a macro, so you'd have to make the function name into a parameterized macro invocation, such as `FUNCTION_NAME(my_calculation, SAMPLESIZE)`, where `SAMPLESIZE` is perhaps `wav16` or `wav32`, and the `FUNCTION_NAME` macro invokes another macro to paste the arguments into a single name. – Jonathan Leffler Jul 18 '12 at 12:33
  • 1
    Closer. See [C Preprocessor and Concatenation](http://stackoverflow.com/questions/1489932/c-preprocessor-and-concatenation/1489985#1489985) for a detailed explanation. I mentioned in my previous comment that you need to have the function name macro invoke another to do the pasting. Even your amended code would generate `my_calculation_sample` regardless of what `sample` was defined to. – Jonathan Leffler Jul 18 '12 at 12:49
  • Thanks ecatmur, this was the solution I ended up implementing, except that I didn't bother wrapping my code in a macro'd function as there was too much stuff to pass back and forth. I actually did thing consider using macro's originally, but I was quite hesitant as heard that they were a "bad idea". Also I was told that they don't play nicely with gdb, but I'll cross that bridge when I come to it. – rhlee Jul 18 '12 at 17:59
2

first of all, a typedef is not a new type, it is an alias or a short form to make things more convenient (especially when working with function pointers)

C is a static language, you cannot create a type during runtime, the type needs to be resolved at compile/link time.

well if it were possible the windows API would be sooo much smaller :)

in windows they have two versions of functions for most every API call and a define that decides which to use.

e.g.

#ifndef UNICODE
#define myfunction _myfunctionA(TCHAR* p);
#else
#define myfunction _myfunctionW(TCHAR* p);
#endif

but again, the type is decided at compile time

AndersK
  • 35,813
  • 6
  • 60
  • 86
2

On the other hand, you can use typedef only in some scope.

int 
main(void) {
    if (1) {
        typedef short sample;
        sample n; // OK
    }
    sample u; // ERROR
    return 0;   
}
md5
  • 23,373
  • 3
  • 44
  • 93
0

The types in C (and C++) are fixed at compile time; the concept of a 'runtime typedef' does not make sense in C.

However, your problem is solvable with care. You will define two sets of functions (and types), one to deal with 16-bit .wav files and one to deal with 32-bit .wav files. These will be defined at compile time, and the sizes of the types will be fixed at compile time, but both lots of code will be in the executable, and you'll be able to choose which set of functions to execute based on run-time information (the type of file you're asked to process, or produce).

Your two sets of functions should be symmetric. You might be able to use some 'template-like' mechanism so that you compile the same file twice, once for the 32-bit code, once for the 16-bit code, ensuring that the function names are changed consistently.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278