I'm very new to C. I want to write C-code that I will wrap in Cython.
This is my C-code (a random-value generator based on a seed):#include <math.h>
typedef struct {
int seed;
int bits;
int max;
double fmax;
int value;
} rGen;
rGen rGen_Init(int seed, int start, int bits) {
rGen gen;
int max = pow(2, bits);
gen.seed = seed % max;
gen.bits = bits;
gen.max = max;
gen.fmax = (double) max;
gen.value = start % max;
return gen;
}
double rGen_Next(rGen gen) {
int value = gen.value;
value = (gen.seed << gen.bits) * value / (gen.bits + 1);
value = pow(value, 4);
value = value % (gen.max - 1);
gen.value = value;
return (double) value / gen.fmax;
}
Doing a little check if the value
attribute of the rGen instance does change:
#include "pyran.c"
#include <stdio.h>
int main() {
rGen gen = rGen_Init(1000, 200, 32); // Create an initialized struct-instance
int i;
for(i = 0; i < 10; i += 1) {
rGen_Next(gen);
printf("%i\n", gen.value);
}
return 0;
}
The output is:
200
200
200
200
200
200
200
200
200
200
The value of the v开发者_StackOverflow社区alue
attribute does not change.
Why does it behave like this ? Do I have to use pointers ? And if so, how do I use them ?
rGen_Next
takes its argument by value, modifies the copy and discards it. To actually modify it, take a pointer argument.
double rGen_Next(rGen* gen) {
int value = gen->value;
value = (gen->seed << gen->bits) * value / (gen->bits + 1);
value = pow(value, 4);
value = value % (gen->max - 1);
gen->value = value;
return (double) value / gen->fmax;
}
Call it like this: rGen_Next(&gen);
if gen
is a variable with automatic storage duration.
Also: It is good C practice to have an init function that takes a pointer to the object actually being initialized.
This way it is up to the user how the structure is allocated.
bool rGen_Init(rGen* gen, int seed, int start, int bits) {
int max = pow(2, bits);
gen->seed = seed % max;
gen->bits = bits;
gen->max = max;
gen->fmax = (double) max;
gen->value = start % max;
// omit the return if there is no chance of failure,
return true;
}
The lifetime of gen
instance defined in rGen_init
terminates when function returns. You can define the function rGen_init(struct rGen *gen,...)
and modify parameter gen
using this pointer.
精彩评论