2014-08-31 79 views
2

srand man表示srand的参数为unsignd int, ,但是在不使用转换的情况下使用时,编译不会发生抱怨。 如果你不使用 (unsigned int)铸造有任何出错的机会?或者没有区别,因为编译器 总是会隐式转换它?如果srand函数的参数是一个负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 

我将假定编译器将隐式转换int类型的变量x在unsigned int 。 这次转换会发生什么? 如果转换将变量(类型为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); 

而且,behinde场景,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 

所以,总是负数转换后,将这样的表现? 我该如何照顾这个?

回答

3

应当隐式转换,用-Wconversion用gcc和铛应提供这样的警告,铛给出以下警告:

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

用于这种转换的规则在所述draft C99 standard6.3.1.3符号和无符号整数它说(重点煤矿):

  1. 当整数类型的值转换为除_Bool以外的其他整数类型 时,如果该值可以用新类型表示,则其 不会更改。

  2. 否则,如果新类型是unsigned,该值是由 转换反复加上或减去小于 可以在新的类型,直到该值是在 的范围内表示的最大值一个更新的类型。49)

  3. 否则,新类型将被签名且其值不能被表示为 ;结果是实现定义的或实现定义的信号被引发。

因此,对于你的第一个例子-2转换为unsigned int类型是:

UINT_MAX + 1 + -2 

这是UINT_MAX - 1,这导致了-1总是会转化为最大的有用的属性对于您正在使用的任何无符号类型,无符号值。您可以使用limits.h得到UINT_MAX

签名的情况下是不同的并且由paragrah覆盖上述,它是实现定义,这意味着编译器决定如何处理这种情况下,所以你必须阅读文档如有提供了解会发生什么这里。例如implementation defined behavior section for integers对于这种情况下表示:

  • 的结果,或(通过所提出的信号的整数变换,以当该值不能在该类型的一个目的 表示的 符号整型C90 6.2.1.2,C99和C11 6.3.1.3)。

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

所以对待签署情况类似签名的情况下,这个数字只是翻过身,它不会导致被提升的信号。因此,对于gcc这是明确的行为,但这不是可移植的行为,所以不应该依赖。

+0

还有一个问题你可能知道,我观察到,当我尝试将一个大于它所支持的“int”变量赋值给一个“int”变量时,会出现类似的行为。那么,什么是计算知道它将存储在变量上的值是多少,我试图存储一个比它支持的值更大的值?这将帮助我了解它是如何实施的。 – ViniciusArruda 2014-08-31 06:17:56

+0

首先感谢这个链接,对我会有很大的帮助,但是,对于坚持我抱歉,我读了文档,但没有找到显示数字如何存储的情况,case大于类型支持。我希望能够详细报告会议6.3.1.3。 – ViniciusArruda 2014-09-01 13:17:33

+0

我想我明白了。我在网上发现了一些关于整数溢出的内容。那么,在这种情况下,这就是我的意思?或仅当涉及算术时存在整数溢出? [整数溢出](http://en.wikipedia.org/wiki/Integer_overflow)和[未定义的行为](http://en.wikipedia.org/wiki/Undefined_behavior) – ViniciusArruda 2014-09-01 13:56:55

0

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

void srand (unsigned int seed); 

因此,如果你给出了否定的int srand函数为一个参数,srand函数会将负的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 

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