2013-09-17 1 views
3

Ну, сегодня я сделал небольшую функцию, которая должна генерировать мне небольшую случайную строку.modulo - неправильный порядок операнда gcc? или UB?

std::string randString(size_t length) 
{ 
    std::string randStr; 
    for(unsigned int i = 0; i < length; i++) 
     randStr.append(1, (char) rand() % 26 + 65); 
    return randStr; 
} 

Я ожидал получить только заглавные буквы, но на самом деле я получил также другие символы, такие как «3» или «)» тоже. Поэтому я предположил, что есть какой-то порядок ошибки операнда. И с круглыми скобками по модулю я получаю ожидаемый результат! Я дополнительно искал порядок работы как по модулю, так и по добавлению, и он говорит, что modulo имеет более высокий приоритет! Может ли кто-нибудь объяснить мне, почему я должен выслушать этот модуль?

Я использую GCC 4.1.2

+1

оператора приоритет ... – devnull

ответ

4

operator % имеет более высокий приоритет, чем oeprator+, НО отливка имеет еще выше ,

Итак, у вас есть неопределенные реализация (благодаря @JamesKanze) определенное поведение здесь, потому что там переполнение signed char.

Вам не нужно окружить скобкой «по модулю» оператора, но отливки, как вы хотите, чтобы бросить окончательный результат: (char)(rand() % 26 + 65)

+0

хорошо, и я не переполняю, если я делаю modulo заранее, вот почему я получаю ожидаемый результат. очень интересно, спасибо большое! –

+1

@PhilippMichalski - да, точно, просто листинг окончательного результата будет более «читаемым» :) Это немного сложный вопрос, мне потребовалось некоторое время, чтобы понять это. –

+0

@KirilKirov Не определено поведение, но реализация определена. И даже если он обертывает (наиболее частое поведение), результаты кастинга на 'char' могут быть отрицательными. –

2

Да, отливка тип имеет более высокий приоритет, то % и + (но ниже, чем вызов функции), так что порядок здесь:

rand() 
((char) rand()) 
((char) rand()) % 26 
(((char) rand()) % 26) + 65 

Когда вы не уверены в приоритете оператора, всегда добавляйте скобки! Они не болят, но помогают избежать таких ошибок. Для того, чтобы получить результат, который вы хотели, вы должны добавить скобки, чтобы сделать отливку Последним типа пойти:

(char) (rand() % 26 + 65); 

Вот таблица для справки: http://en.cppreference.com/w/cpp/language/operator_precedence

+3

Еще одна причина не использовать C- стиль в C++-коде. Даже семантически эквивалентный стиль функции cast 'char (rand()% 26 + 65)' решил бы это, не говоря уже о 'static_cast (:::)'. – Angew

+0

О, черт возьми, я полностью забыл, что литой тоже оператор :-D спасибо –

+0

Если вы не уверены в приоритете оператора, ** посмотрите его **. Ненужные круглые скобки ** боятся **: в лучшем случае они отвлекают читателей, которые знают, как работает язык, и в худшем случае они делают читателей подозрительными к компетенции писателя. Вы действительно хотите пробираться через '((char) ((rand()% 26) +65))'? –