繁体   English   中英

如果srand函数的参数为​​负int,在幕后会发生什么?

[英]What happens behind the scenes if the parameter of srand function is an negative int?

srand mansrand作为参数是一个无符号的int,但是在不转换的情况下使用时不会抱怨。 如果不使用cast with (unsigned int)是否有可能出错? 是否有所不同,因为编译器始终会隐式转换它?

例如,下面的代码:

#include<stdio.h>
#include<stdlib.h>

int
main(void)
{
    int num, x;

    x = -2;

        srand(x);
    num = rand() % 100000;

    printf("%d\n", num);

    return 0;
}

此代码的打印结果是:

32

我将假定编译器将在unsigned int隐式转换int类型的变量x。 这次转换会怎样? 如果转换将变量(类型为int )转换为unsigned int ,而该值与生成种子后变量的其他数字相同,那么该怎么办呢? 换一种说法:

int x = -2;
int y = 546; // the number 546 is just an example !

int num_x = srand(-2);
int num_y = srand(546);

并且,在幕后, num_x等于num_y

当我对自己的评分负数并且我怀疑这种种子是否独特时,就会出现这种怀疑。 我认为不是,因为例如以下代码:

#include<stdio.h>
#include<stdlib.h>

int
main(void)
{
    int t, num;
    t = -6;

    printf("%u\n", t);  // prints the variable t as unsigned (implicitly converted)
        srand(t);
    num = rand() % 100000;
    printf("Random number: %d\n", num);

    srand(4294967290);   // the number 4294967290 is how the int number -6 looks like when converted in unsigned int
    num = rand() % 100000;
    printf("New random number: %d\n", num);
    return 0;
}

它的输出:

4294967290
Random number: 19
New random number: 19

那么,转换后始终为负数的行为会是这样吗? 我该如何处理?

它将被隐式转换,将-Wconversion与gcc和clang一起使用应为此提供警告,clang提供以下警告:

warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
    srand(x);
    ~~~~~ ^

草案C99标准6.3.1.3节涵盖了用于此转换的规则,有符号和无符号整数表示( 强调我的 ):

  1. 将具有整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则该值不变。

  2. 否则,如果新类型是无符号的 ,则通过重复添加或减去比新类型可表示的最大值多一个值来转换该值,直到该值在新类型的范围之内(49)。

  3. 否则,将对新类型进行签名,并且无法在其中表示值; 结果是实现定义的,还是引发实现定义的信号。

因此,对于您的第一个示例,将-2转换为unsigned int是:

UINT_MAX + 1 + -2

这是UINT_MAX - 1 ,这将导致有用的属性,无论您使用哪种无符号类型, -1始终将转换为最大无符号值。

您可以使用limits.h获取UINT_MAX

带符号的情况有所不同,上面的第3段对此进行了介绍,它是由实现定义的,这意味着编译器决定如何处理这种情况,因此,如果有任何说明,则您必须阅读文档以了解此处将发生的情况。 例如, 针对整数的实现定义的行为部分说明了这种情况:

  • 当值不能在该类型的对象(C90 6.2.1.2,C99和C11 6.3.1.3)中表示时,将整数转换为有符号整数类型的结果或发出的信号。

    为了转换为宽度为N的类型,将值模2 ^ N减小到该类型的范围内; 没有信号发出。

因此,它将已签名的情况与未签名的情况类似,数字只是翻转而不会引起信号发出。 因此,对于gcc这是定义明确的行为,但这不是可移植行为,因此不应依赖。

我认为您的想法是正确的,因为在头文件“ stdlib.h”中,srand函数的声明为:

void srand (unsigned int seed);

因此,如果您给srand函数一个负整数作为参数,则srand函数g会将负整数转换为unsigned int。

这是一个例子:

#include<stdio.h>
#include<stdlib.h>

int test(unsigned int data)
{
    if(data == 4294967290)
    {
        return 1;
    }
    else
        return 99;
}
int
main(void)
{
    int i;

    i = -6;
    printf("negative parameter : %d\n", test(i));

    i = 4294967290;
    printf("unsigned parameter : %d", test(i));


    return 0;
}

它的输出:

negative parameter : 1
unsigned parameter : 1

希望我的回答对您有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM