Converting from unsigned long int to signed int an

2019-08-27 02:07发布

问题:

I would like to pass a signed int to gsl_rng_uniform_int (const gsl_rng * r, unsigned long int n). The signed int that I'm passing is greater than or equal to zero. The function will return a number between 0 and n, so if I pass it a positive signed int, it will return something that is in the range of a signed int. I then want to store the return value in a signed int. What's the cleanest way to do this with the obvious expected behaviour? I'm on a 64-bit compiler on a 64-bit Linux machine.

Update Sorry, folks. Please ignore. The problem with my code was actually elsewhere. I misinterpreted the output of gdb.

回答1:

Start with:

int input = something;
int result = gsl_rng_uniform_int(r, input);

Likely the compiler will warn about an unsafe narrowing conversion, so change to:

// 0 <= return value < input, so conversion is safe
int result = (int) gsl_rng_uniform_int(r, input);

Or for safety:

if (input <= 0) { panic(); }
unsigned long rawresult = gsl_rng_uniform_int(r, input);
if (rawresult > INT_MAX) { panic(); }
int result = (int) rawresult;

Those lines could be wrapped in a helper function:

int gsl_rng_uniform_signed(const gsl_rng *r, int input) {
    if (input <= 0) { panic(); }
    unsigned long rawresult = gsl_rng_uniform_int(r, input);
    if (rawresult > INT_MAX) { panic(); }
    return (int) rawresult;
}

In any case testing your input is typically more useful than testing the output of functions you rely on, and if you trust gsl_rng_uniform_int then testing the input is sufficient.

[Edit: wow, Google indexes SO really aggressively. I just searched to check that gsl_rng_uniform_signed isn't already a function, and found myself.]



回答2:

If the function expects an unsigned long you can pass with no problem an unsigned long, unsigned int, unsigned short and unsigned char, the standard guarantees that.

If you pass a signed but negative int, you will not obtain the correct results, since it will be evaluated to a very big int by the function.

The best way is to check if it the signed int is >= 0 before passing it.

I hope I understood your question correctly.