2014-08-31 4 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 в 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.

Это сомнение появилось, когда у меня был отрицательный параметр на моем srand, и я сомневался, будет ли это семя уникальным. Я думаю, что это не так, потому что для примера, код ниже:

#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 с НКОЙ и лязгом должны обеспечить предупреждение для этого, лязг дает следующее предупреждение:

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

правило, используемое для такого преобразования рассматривается в разделе draft C99 standard6.3.1.3Подпись и целые числа без знака который говорит (внимание мое):

  1. Когда значение с целым типом преобразуется в другой целочисленный тип , отличный от _Bool, если значение может быть представлено новым типом, оно равно .

  2. В противном случае, если новый тип без знака, значение преобразуется с помощью многократно прибавления или вычитания один больше, чем максимальное значение, которое может быть представлена ​​в новом типе, пока значение не находится в диапазоне новый тип.49)

  3. В противном случае новый тип подписан и значение не может быть представлено ; либо результат определяется реализацией, либо генерируется сигнал, определяемый реализацией .

Таким образом, для первого примера -2 преобразуется в неподписанном INT будет:

UINT_MAX + 1 + -2 

которого UINT_MAX - 1, это приводит к полезному свойству, что -1 всегда будут преобразованы в макс unsigned значение для любого беззнакового типа, который вы используете.

Вы можете использовать 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' число, большее, чем оно поддерживает. Итак, каков расчет, чтобы узнать, какое значение он будет хранить в переменной, в которой я пытался сохранить большее значение, чем он поддерживает? Это поможет мне узнать, как это реализовано. – ViniciusArruda

+0

Первое спасибо за ссылку, мне очень поможет, но, извините за настоятельную необходимость, я прочитал документы, но не нашел того, что показывало, как количество хранимых случаев больше, чем тип поддержки. Мне хотелось бы что-то вроде сеанса 6.3.1.3, который подробно рассказывает. – ViniciusArruda

+0

Я думаю, что понял. Я нашел что-то в Интернете, говоря о переполнении целого числа. Итак, в этом случае, вот что я имею в виду? Или целочисленное переполнение существует только при наличии арифметики? [integer overflow] (http://en.wikipedia.org/wiki/Integer_overflow) и [неопределенное поведение] (http://en.wikipedia.org/wiki/Undefined_behavior) – ViniciusArruda

0

Я думаю, что ваша идея верна, потому что в голове файл «stdlib.h», декларация функции srand является:

void srand (unsigned int seed); 

Поэтому, если вы даете отрицательный Int функции srand как параметр 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 

Я надеюсь, что мой ответ полезным для вас.