如果srand函数的参数是负int,那么幕后会发生什么?

时间:2014-08-31 02:43:13

标签: c random casting implicit-conversion srand

srand man表示srand的参数为unsignd int, 但是在没有强制转换的情况下使用时,编译不会抱怨。 如果你不使用演员,有任何出错的机会 (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

我将假设编译器将隐式转换intunsigned 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

那么,转换后的负数总是会这样吗? 我该如何处理这个?

2 个答案:

答案 0 :(得分:3)

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

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

draft C99 standard部分6.3.1.3 有符号和无符号整数强调我的)中涵盖了用于此转换的规则:< / p>

  
      
  1. 当整数类型的值转换为另一个整数类型时   除了_Bool之外,如果值可以用新类型表示,那么   没有变化。

  2.   
  3. 否则,如果新类型为无符号,则转换为   重复加或减一个以上的最大值   可以用新类型表示,直到值在范围内   新类型.49)

  4.   
  5. 否则,新类型已签名且无法表示该值   在里面;结果是实现定义的还是   提出了实现定义的信号。

  6.   

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

UINT_MAX + 1 + -2

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

您可以使用limits.h获取UINT_MAX

签名的案例是不同的,并且由上面的段落 3 涵盖,它是实现定义的,这意味着编译器决定如何处理这种情况,所以你必须阅读文档,如果有任何提供给明白这里会发生什么。例如implementation defined behavior section for integers对于这种情况说:

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

         

    为了转换为宽度为N的类型,该值以2 ^ N为模减少   在该类型的范围内;没有信号被提出。

  •   

所以它处理类似于unsigned case的签名情况,数字只是翻转而且不会引发信号。因此,对于gcc,这是明确定义的行为,但这不是可移植的行为,因此不应该依赖它。

答案 1 :(得分:0)

我认为你的想法是正确的,因为在头文件&#34; stdlib.h&#34;中,声明  srand函数是:

void srand (unsigned int seed);

因此,如果将srand函数的负int赋予参数,则srand functiong会将负int转换为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

我希望我的答案对你有用。