无法理解这段 C 语言的 PRNG 代码

发布于 2024-11-08 02:34:41 字数 1411 浏览 2 评论 0原文

#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 不太有经验,这段代码中的一些内容对我来说完全没有意义。我尝试对代码进行注释以跟踪发生的情况。如果我不明白的一些事情能够得到澄清,我将不胜感激。特别是具有相同名称的变量和函数的声明,以及 initnd 子例程,似乎没有在程序或我在互联网上找到的任何库中定义。

多谢。

#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);
}

This is some code for a PRNG. I am not very experienced with C and some of the things in this code make absolutely no sense to me. I tried to comment to code to track what's going on. I would appreciate it if some of the things I don't understand could be cleared up. Especially the declarations of variables and functions with the same name, as well as the initrnd subroutine, that doesn't seem to be defined in the program or any library I could find on the internet.

Thanks a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

痕至 2024-11-15 02:34:41

这看起来确实很古老。

对您问题的一些回答:

  1. 不,原型不需要是外部函数。这也许是最常见的,但不是必需的。
  2. initrnd() 只是将全局 seed 变量设置为特定值,然后在 PRNG 中使用。
  3. 数据写入stdout;假设使用文件描述符 1。这种神奇常量的使用不太漂亮,它应该写成 stdout (来自 )。

This looks positively ancient.

A few answers to your questions:

  1. No, prototypes don't need to be outside functions. It's most common, perhaps, but not required.
  2. initrnd() just sets the global seed variable to a specific value, that is then used in the PRNG.
  3. The data is written to stdout; which is assumed to be using file descriptor 1. This use of a magical constant is not very pretty, it should be written as stdout (from <stdio.h>).
棒棒糖 2024-11-15 02:34:41
   /* 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,但它应该是void(无论如何它没有任何区别),也许原来的程序员很懒:P

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

because ne is an integer and sd is a double, therefore the cast is needed

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

it is the last function, it sets the global variable seed with its parameter

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

the file descriptor is 1, which stands for standard output, so this is like calling printf()

initrnd(sd)

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

this function is int, but it should be void (it doesn't make any difference anyway), perhaps the original programmer was lazy :P

云裳 2024-11-15 02:34:41

该代码是标准 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);
}

The code is pre-standard C, so it's not using prototypes (but does declare functions, though apparently not unless absolutely necessary). The function definitions use the pre-standard K&R style of declaring the parameters to the function. With non-protoyped functions, it incumbent on the programmer to ensure that the functions are called with the correct set of arguments, and that if a function returns nothing, then nothing is done with the function's 'value'.

If something other than an int is returned from a function, then the function must be declared (which is not necessarily a prototype) so the compiler is aware of the type of data returned from the function. Without a declaration, the compiler will assume that an int is returned (but if nothing is returned by the function, that's OK as long as you don't try to do anything with the function 'result').

Here are some direct comments to your questions:

   /* 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文