2014-08-31 80 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 

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