возникли проблемы с пониманием этого кода PRNG в C - PullRequest
0 голосов
/ 18 мая 2011
#include <stdio.h>


double seed=0.579832467;

main(ac, av)
int ac;
char *av[];
  {
   /* declare variables */
   float *buf, fac;
   int sf, ne, i;

   /* prototypes? ( shouldn't they be outside the main ) */
   double rnd(), sd;

   /* gets the number of elements from command line */
   ne = atoi(av[1]);

   /* assigns the size of float ( in bytes ) to integer value */
   sf = sizeof(float);

   /* allocates appropriate memory for random number generation */
   buf = (float *)malloc(ne*sf);

   /* type cast, why?? */
   sd = (double)(ne);

   /* no idea what initrnd does */
   initrnd(sd/(sd+187.9753));

   /* checks if memory allocation is successful */
   if (buf == NULL)
     {
      fprintf(stderr, "rndneg: can't allocate %d bytes for buffer\n", ne*sf);
      exit(-1);
     }

   /* fills buffer with random number */
   for (i=0; i<ne; i++)
    {
     buf[i] = (float)(rnd());
    }

   /* writes the buffer, how does it know the file name? */ 
   write(1, buf, ne*sf);
}

/* random number generating function */
double rnd()
{
seed *= 997.0;
seed -= (double)((int)(seed));
return(seed);
}


initrnd(sd)

/* again no idea, why isn't this function void */
double sd;
{
seed = sd;
return(0);
}

Это некоторый код для PRNG.Я не очень разбираюсь в C, и некоторые вещи в этом коде не имеют для меня никакого смысла.Я попытался прокомментировать код, чтобы отслеживать, что происходит.Я был бы признателен, если бы некоторые вещи, которые я не понимаю, могли быть прояснены.Особенно объявления переменных и функций с одинаковыми именами, а также подпрограммы initrnd, которые, кажется, не определены ни в программе, ни в какой-либо библиотеке, которую я мог найти в Интернете.

Большое спасибо.

Ответы [ 3 ]

2 голосов
/ 18 мая 2011

Это выглядит положительно древним.

Несколько ответов на ваши вопросы:

  1. Нет, прототипы не должны быть внешними функциями.Это наиболее часто, возможно, но не обязательно.
  2. initrnd() просто устанавливает глобальную переменную seed на определенное значение, которое затем используется в PRNG.
  3. Данные записываютсядо stdout;предполагается, что используется файловый дескриптор 1.Такое использование магической константы не очень красиво, оно должно быть записано как stdout (из <stdio.h>).
1 голос
/ 18 мая 2011
   /* type cast, why?? */
   sd = (double)(ne);

, поскольку ne является целым числом, а sd является двойным, поэтому приведение необходимо

   /* no idea what initrnd does */
   initrnd(sd/(sd+187.9753));

это последняя функция, она устанавливает глобальную переменную seed с параметром

   /* writes the buffer, how does it know the file name? */ 
   write(1, buf, ne*sf);

дескриптор файла равен 1, что означает стандартный вывод, так что это похоже на вызов printf ()

initrnd(sd)

/* again no idea, why isn't this function void */

эта функция имеет тип int, но она должна быть недействительной (она не делаетлюбая разница в любом случае), возможно, оригинальный программист был ленив: P

0 голосов
/ 19 мая 2011

Код является предстандартным C, поэтому он не использует прототипы (но объявляет функции, хотя, по-видимому, нет, если в этом нет крайней необходимости).В определениях функций используется предварительно стандартный стиль K & R для объявления параметров функции.С непрототипированными функциями на программиста возлагается обязанность гарантировать, что функции вызываются с правильным набором аргументов, и что если функция ничего не возвращает, то ничего не делается с ее «значением».

Если из функции возвращается что-то отличное от int, функция должна быть объявлена ​​(что не обязательно является прототипом), чтобы компилятор знал тип данных, возвращаемых из функции.Без объявления компилятор будет считать, что возвращается int (но если функция ничего не возвращает, это нормально, если вы ничего не пытаетесь сделать с функцией 'result').

Вот несколько прямых комментариев к вашим вопросам:

   /* prototypes? ( shouldn't they be outside the main ) */
   //   this declares that function `rnd()` returns a double.  Technically, it's 
   //   not a prototype. Without the declaration the compiler would assume that it 
   //   returns an `int` so trying to use it wouldn't work.  It could be declared 
   //   outside `main()`, but it's OK to have it declared within the scope of 
   //   `main()`, just like it would be for a prototype.  That just means that 
   //    outside of `main()` the declaration is no longer in effect, so any calls
   //    to `rnd()` would assume that `int` is returned (incorrectly).
   double rnd(), sd;


   /* type cast, why?? */
   //   the cast is unnecessary and redundant, but OK
   sd = (double)(ne);

   /* no idea what initrnd does */
   //   apparently `initrnd()` initializes the rng seed (see below). There's
   //   no declaration in sight, so the compiler will default the return type 
   //   to `int` (unless it's in `stdio.h`).
   initrnd(sd/(sd+187.9753));

   /* writes the buffer, how does it know the file name? */ 
   //   `1` is the file descriptor for `stdout`.  Today this would probably
   //   be specified using `STDOUT_FILENO`, but even today `STDOUT_FILENO` is 
   //   required to be 1 (by POSIX).
   write(1, buf, ne*sf);
}

initrnd(sd)

/* again no idea, why isn't this function void */
//  `void` didn't exist pre-ANSI standard.
//  so this function 'returns' `int` by default.
double sd;
{
seed = sd;
return(0);
}
...