Programowanie w systemie UNIX/preprocesor

Z Wikibooks, biblioteki wolnych podręczników.

opcje kompilatora[edytuj]

Opcja -E - powoduje wygenerowanie kodu programu ze zmianami, wprowadzonymi przez preprocesor, np.:

gcc m.c -E -o t.c

Efektem jest: [1]

  • rozwinięcie dyrektyw #define
  • rozwiązanie dyrektyw #include
  • włączenie deklaracji wszystkich funkcji do kodu źródłowego
  • usunięcie komentarzy


Można również użyć bezpośrednio prepocesora cpp: [2]

cpp m.c > add.i


gcc -S t.c

powoduje zapisanie pliku t.s zawierającego efekt działania preprocesora

Jak z pliku wygenerowanego przez preprocesor odtworzyć plik z kodem w C?[edytuj]

  • przechodzimy do końca pliku
  • odnajdujemy kod w c
  • idziemy do góry (początku pliku)
  • usuwamy linie ze znakiem # na początku, oprócz poleceń OpenMP (pragma)
  • kiedy dochodzimy do linii z "dziwnym" kodem, np.:
  }
# 163 "g:\\progra~1\\dev-c++\\mingw64\\x86_64-w64-mingw32\\include\\malloc.h" 3
  static __inline void __attribute__((__cdecl__)) _freea(void *_Memory) {
    unsigned int _Marker;
    if(_Memory) {
      _Memory = (char*)_Memory - 16;
      _Marker = *(unsigned int *)_Memory;
      if(_Marker==0xDDDD) {
 free(_Memory);
      }
 
 
 
 
 
    }
  }
# 209 "g:\\progra~1\\dev-c++\\mingw64\\x86_64-w64-mingw32\\include\\malloc.h" 3
#pragma pack(pop)
# 669 "g:\\progra~1\\dev-c++\\mingw64\\x86_64-w64-mingw32\\include\\stdlib.h" 2 3
# 3 "test.c" 2

to usuwamy wszystkie linii aż do początku pliku

  • dodajemy wymagane biblioteki (include)

Jest to przydatne gdy programista używa preprocesora do tworzenia różnych wersji procedur. Przykładowo z kodu:[3]

FTYPE FNAME(cabs2)(complex FTYPE z) {
  return FNAME(creal)(z) * FNAME(creal)(z) + FNAME(cimag)(z) * FNAME(cimag)(z);
}

complex FTYPE FNAME(coordinate)(int i, int j, int width, int height, complex FTYPE center, FTYPE radius) {
  FTYPE x = (i - width /FNAME(2.0)) / (height/FNAME(2.0));
  FTYPE y = (j - height/FNAME(2.0)) / (height/FNAME(2.0));
  complex FTYPE c = center + radius * (x - I * y);
  return c;
}

int FNAME(calculate)(complex FTYPE c, int maximum_iterations, FTYPE escape_radius2) {
  complex FTYPE z = 0;
  int final_n = 0;
  for (int n = 1; n < maximum_iterations; ++n) {
    z = z * z + c;
    if (FNAME(cabs2)(z) > escape_radius2) {
      final_n = n;
      break;
    }
  }
  return final_n;
}

void FNAME(render)(int width, int height, complex FTYPE center, FTYPE radius, int maximum_iterations, FTYPE escape_radius2) {
  printf("P5\n%d %d\n255\n", width, height);
  for (int j = 0; j < height; ++j) {
    for (int i = 0; i < width; ++i) {
      complex FTYPE c = FNAME(coordinate)(i, j, width, height, center, radius);
      int final_n = FNAME(calculate)(c, maximum_iterations, escape_radius2);
      putchar(final_n);
    }
  }
}

otrzymujemy:

float pif = 3.14159265358979323846264338327950288419716939937510f;

float cabs2f(_Complex float z) {
  return crealf(z) * crealf(z) + cimagf(z) * cimagf(z);
}

_Complex float coordinatef(int i, int j, int width, int height, _Complex float center, float radius) {
  float x = (i - width /2.0f) / (height/2.0f);
  float y = (j - height/2.0f) / (height/2.0f);
  _Complex float c = center + radius * (x - (__extension__ 1.0iF) * y);
  return c;
}

void calculatef(struct pixel *out, _Complex float c, int maximum_iterations, float escape_radius2) {
  out->final_n = 0;
  out->final_z = 0;
  _Complex float z = 0;
  for (int n = 1; n < maximum_iterations; ++n) {
    z = z * z + c;
    if (cabs2f(z) > escape_radius2) {
      out->final_n = n;
      out->final_z = z;
      break;
    }
  }
}

void renderf(struct image *img, _Complex float center, float radius, int maximum_iterations, float escape_radius2) {
#pragma omp parallel for
  for (int j = 0; j < img->height; ++j) {
    for (int i = 0; i < img->width; ++i) {
      _Complex float c = coordinatef(i, j, img->width, img->height, center, radius);
      calculatef(&img->pixels[j * img->width + i], c, maximum_iterations, escape_radius2);
    }
  }
}

double pi = 3.14159265358979323846264338327950288419716939937510;

double cabs2(_Complex double z) {
  return creal(z) * creal(z) + cimag(z) * cimag(z);
}

_Complex double coordinate(int i, int j, int width, int height, _Complex double center, double radius) {
  double x = (i - width /2.0) / (height/2.0);
  double y = (j - height/2.0) / (height/2.0);
  _Complex double c = center + radius * (x - (__extension__ 1.0iF) * y);
  return c;
}

void calculate(struct pixel *out, _Complex double c, int maximum_iterations, double escape_radius2) {
  out->final_n = 0;
  out->final_z = 0;
  _Complex double z = 0;
  for (int n = 1; n < maximum_iterations; ++n) {
    z = z * z + c;
    if (cabs2(z) > escape_radius2) {
      out->final_n = n;
      out->final_z = z;
      break;
    }
  }
}

void render(struct image *img, _Complex double center, double radius, int maximum_iterations, double escape_radius2) {
#pragma omp parallel for
  for (int j = 0; j < img->height; ++j) {
    for (int i = 0; i < img->width; ++i) {
      _Complex double c = coordinate(i, j, img->width, img->height, center, radius);
      calculate(&img->pixels[j * img->width + i], c, maximum_iterations, escape_radius2);
    }
  }
}

long double pil = 3.14159265358979323846264338327950288419716939937510l;

long double cabs2l(_Complex long double z) {
  return creall(z) * creall(z) + cimagl(z) * cimagl(z);
}

_Complex long double coordinatel(int i, int j, int width, int height, _Complex long double center, long double radius) {
  long double x = (i - width /2.0l) / (height/2.0l);
  long double y = (j - height/2.0l) / (height/2.0l);
  _Complex long double c = center + radius * (x - (__extension__ 1.0iF) * y);
  return c;
}

void calculatel(struct pixel *out, _Complex long double c, int maximum_iterations, long double escape_radius2) {
  out->final_n = 0;
  out->final_z = 0;
  _Complex long double z = 0;
  for (int n = 1; n < maximum_iterations; ++n) {
    z = z * z + c;
    if (cabs2l(z) > escape_radius2) {
      out->final_n = n;
      out->final_z = z;
      break;
    }
  }
}

void renderl(struct image *img, _Complex long double center, long double radius, int maximum_iterations, long double escape_radius2) {
#pragma omp parallel for
  for (int j = 0; j < img->height; ++j) {
    for (int i = 0; i < img->width; ++i) {
      _Complex long double c = coordinatel(i, j, img->width, img->height, center, radius);
      calculatel(&img->pixels[j * img->width + i], c, maximum_iterations, escape_radius2);
    }
  }
}

odnośniki[edytuj]

  1. quora : What-are-useful-tricks-in-C++-or-C-that-beginners-rarely-know ?
  2. embhack: stages-of-compilation-in-c-program/
  3. book program by Claude Heiland-Allen