Re[2]: Всё очень просто....
От: Шахтер Интернет  
Дата: 13.11.06 10:15
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Аноним, Вы писали:


А>>Что вы думаете по этому поводу?


E>signed -- для чисел

E>unsigned -- для флажков.

По-моему, это та простота, которая хуже воровства.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 13.11.06 10:29
Оценка: 6 (1) +2
Здравствуйте, Аноним, Вы писали:

А>Что вы думаете по этому поводу?


В моём коде чаще всего используются беззнаковые переменные, чем знаковые.
Причин тут несколько.

1) Беззнаковая арифметика имеет точно определённую семантику, в отличии от знаковой.

2) В беззнаковой арифметике лего ловить переполнение.

unsigned a=...;   
unsigned b=...;

a+=b;

if( a<b ) 
  { //overflow  
   ... 
  }


3) В C/C++ размерности массивов выражаются беззнаковым типом size_t. По этой причине ипользовать для индексирования знаковые типы -- создавать потенциальные дыры.

4) LUT удобнее делать с беззнаковыми типами. Классический пример.

bool CharIsXXX(char c)
 {
  static const bool table[256]={...};

  return table[(unsigned char)c];
 }
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[8]: Нужен ли unsigned
От: vsb Казахстан  
Дата: 13.11.06 11:08
Оценка: 6 (1)
Здравствуйте, night beast, Вы писали:

NB>если не ошибаюсь, сравнение с указателем который указывает не на "элемент массива или элемент после конечного" -- UB.


NB>зачем так мне не известно.


Здесь можно почитать дискуссию по этому поводу: http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/756952acd8905e18/639bcb0527d875c2

Например
The 80386 memory access model is quite
complicated and there are many ways to implement a "pointer".
One involves a pair (selector,offset) and loading a wrong selector
in any of the selector registers is an error (General Protection Fault
if I remember correctly). Deleting an object could result in freeing
the entry in a selector translation table and subsequent load of the
pointer value could fail.
Re[6]: Нужен ли unsigned
От: Кодт Россия  
Дата: 13.11.06 11:38
Оценка: +2
Здравствуйте, Шахтер, Вы писали:

К>>В знаковой арифметике одно и то же неравенство можно выразить несколькими способами: x<y, x-y<0, 0<y-x, а в


Ш>В знаковой арифметике эти выражения точно так же не эквивалетны. Кроме того, x<0 не эквивалетно -x>0.


Ну не "точно так же". Конечно, в области больших чисел есть риск поймать переполнение.
Но предусловие "оба числа по абсолютному значению не превосходят MAXINT/2" достаточно распространено, и этим можно пользоваться.

Кстати говоря. Это и плюс, и минус одновременно. С одной стороны, упрощаются выражения, а с другой — есть риск забыть проверки и получить феерверк на больших значениях. Беззнаковая же арифметика не прощает халатности с самого начала.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Всё очень просто....
От: Erop Россия  
Дата: 13.11.06 11:50
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

E>>signed -- для чисел

E>>unsigned -- для флажков.
Ш>По-моему, это та простота, которая хуже воровства.

Ну прости, я ответил на вопрос, что же я таки думаю.
ИМХО выгоды от использования беззанковых чисел всегда какие-то призрачные.
Конечно есть какие-то специальные очень случаи, когда хочется именно беззнакового и именно 32-ного числа.

Но, это очень большая редкость. Я вот припоминаю только один случай.

Обычно беззнаковые числа хочется использовать для каких-то объектов, которые числами не являютчся (скажем над ними не производят арифметических действий, например).
Это или какие-то ID или сборки флагов или ещё какие-нибудь хитрые конструкции. но никак не результат сложения/вычитания/деления/умножения/взятия остатка.

пример о котором я помню -- млпдшее слово в руками сделанном двухсловном числе.

Кроме того беззнаковость числа ничего хорошего ни в CT ни в RT не гарантирует.
Ну а выгоды я хотел бы узнать (кроме, конечно, выгоды в один бит)

Часто выгода в один бит всё равно бесполезна. Ну и потом обычно это всё непереносимо
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: last_hardcoder  
Дата: 13.11.06 12:11
Оценка: +1
Здравствуйте, Аноним,

Беззнаковые типы не то чтобы не нужны. Однако использовать их для представления ширины или ещё чего-то заведомо положительного нет смысла. Предположим, нам надо сохранить не саму ширину, а разницу между шириной одного и другого окна. Она может быть как положительной, так и отрицательной.
Re[2]: Нужен ли unsigned
От: Sm0ke Россия ksi
Дата: 13.11.06 12:26
Оценка: :))
Здравствуйте, Шахтер, Вы писали:


Ш>3) В C/C++ размерности массивов выражаются беззнаковым типом size_t. По этой причине ипользовать для индексирования знаковые типы -- создавать потенциальные дыры.


Можно написать свой вектор, где отрицательный индекс ведёт отсчёт с конца.

my_vector vec(10);
//vec[-1] == vec[9]
Re[4]: Всё очень просто....
От: night beast СССР  
Дата: 13.11.06 13:11
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>signed -- для чисел

E>>>unsigned -- для флажков.
Ш>>По-моему, это та простота, которая хуже воровства.

E>Ну прости, я ответил на вопрос, что же я таки думаю.

E>ИМХО выгоды от использования беззанковых чисел всегда какие-то призрачные.
E>Конечно есть какие-то специальные очень случаи, когда хочется именно беззнакового и именно 32-ного числа.

у беззнаковых чисел есть одно хорошее свойство -- все арифметические операции делаются по модулю.
но постоянная борьба с варнингами при сравнении знаковых и беззнаковых просто удручает.
Re[7]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 15:29
Оценка: 3 (2)
Здравствуйте, johny5, Вы писали:


АТ>>
АТ>>int a[N];
АТ>>int* p = a + N;

АТ>>while (--p >= a)
АТ>>  *p = 0;
АТ>>


АТ>>Типичный 'int'-овый программист зачатсую даже и не видит проблемы в этом коде. Более того, такой код зачастую "работает". В то время как на самом


J>Что то я действительно не вижу проблем в таком коде...


В один прекрасный момент 'p' станет указывать на начало массива. К такому указателю в языках С/С++ запрещается применять операцию '--', т.е. запрещается пытаться получить указатель на элемент "перед первым" элементом массива. После последнего — можно, перед первым — нельзя. Попытка получить такой указатель приведет к неопределенному поведению. Этот код как раз попытается получить такой указатель.
Best regards,
Андрей Тарасевич
Re[3]: Где тут ошибка
От: Erop Россия  
Дата: 13.11.06 15:37
Оценка: 1 (1) +1 -3
Здравствуйте, Шахтер, Вы писали:

Ш>
Ш>void func(char *p,size_t s)
Ш> {
Ш>  for(int i=0; i<s ;i++) p[i]=0;
Ш> }
Ш>


Ш>Надо обьяснять, где здесь ошибка?


Зачем объяснять?
Ошибка в том, что s имеет беззнаковый тип.
Она же допущена и в std::vector

Ну и что?

1) реально size таким большим не бывает, так как в память плохо помещается
2) Лично я и std::vector не пользуюсь. Пользуюсь массивами из другой библиотеки, там размер массива int
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: А может пусть лучше оптимизатор сокращает? :) (-)
От: Erop Россия  
Дата: 13.11.06 16:03
Оценка:
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: А может проще таки быть проще? :)
От: Erop Россия  
Дата: 13.11.06 16:05
Оценка: +1
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ><...>

АТ>Правильная реализация такого цикла


АТ>
АТ>int a[N];
АТ>int* p = a + N;

АТ>while (p > a)
АТ>  *--p = 0;
АТ>


АТ>является одним из варинатов "шаблонного" решения, применимого и к примеру с unsigned циклом


АТ>
АТ>unsigned someCounter = 99;
АТ>while(someCounter > 0) {
АТ>  --someCounter
АТ>  ...
АТ>}
АТ>


АТ>Я могу лишь посторить, что специфика "близости края интервала", присущая беззнаковым типам и за которую их часто "не любят", в языках С и С++ присуща далеко не только беззнаковым типам. Если внимательно поискать, найти ее можно практически везде. И спрятаться от нее вам не удастся, как бы вы этого не хотели.


А может писать как-то попроще. Скажем так:

int a[N];
for( int i = N - 1; i >= 0; i-- ) {
    a[i] = 0;
}


Компиляторы у нас сейчас хорошие, оптимизирующие. Код вроде как тоже понятный
Ну а то, что так нельзя с итераторами программировать, так, ИМХО, это проблема дизайна итераторов, а не необходимости пользоваться всюду ьеззнаковыми типами
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Всё очень просто....
От: Erop Россия  
Дата: 13.11.06 16:07
Оценка:
Здравствуйте, night beast, Вы писали:

NB>у беззнаковых чисел есть одно хорошее свойство -- все арифметические операции делаются по модулю.

NB>но постоянная борьба с варнингами при сравнении знаковых и беззнаковых просто удручает.


Поясни что ты имеешь в виду под этим "хорошим" свойством.
и от чего оно таки хорошее?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Решите тогда задачу
От: Roman Odaisky Украина  
Дата: 13.11.06 16:44
Оценка: +1
Хорошо, а как «правильно» решить следующую простейшую задачу?

Круг разбит на n > 0 секторов, пронумерованых подряд числами 0, 1, ..., n – 1. Некто стоит в секторе номер 0, затем идет по кругу, делая s шагов. Куда он попадет?

Пример:
nsРезультат
3
3
3
3

3
3
3
3

3
999
4294967295
0
1
2
3

4
-1
-2
-3
-4
-2147483648
-2147483648
0
1
2
0

1
2
1
0

2
718
2147483647
unsigned f(unsigned n, int s)
{
    . . . ?
}
До последнего не верил в пирамиду Лебедева.
Re[7]: А может проще таки быть проще? :)
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 17:28
Оценка:
Здравствуйте, Erop, Вы писали:


E>А может писать как-то попроще. Скажем так:


E>
E>int a[N];
E>for( int i = N - 1; i >= 0; i-- ) {
E>    a[i] = 0;
E>}
E>


E>Компиляторы у нас сейчас хорошие, оптимизирующие. Код вроде как тоже понятный


Не надо фиксироваться на частностях. Мои примеры — лишь иллюстрация общего принципа. Приведенный мною ранее пример доступа с помощью указателя (или итератора) производит честный последовательный доступ к элементам контейнера. Ты же в своем примере эмулируешь последовательный доступ при помощи произвольного доступа. В общем случае это, разумеется, невозможно. И никакой оптимизирующий компиялтор тут тебе не поможет.
Best regards,
Андрей Тарасевич
Re[5]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 17:35
Оценка: :)
Здравствуйте, Кодт, Вы писали:

К><>

АТ>>Я не знаком ни с какими "потенциальными проблемами" беззнаковых типов. В моем коде, например, практически все целочисленные типы — беззнаковые, за исключением случаев, когда действительно приходится работать со знаковой величиной.
К><>

К>Не столько проблема, сколько неудобство (иногда).

К>В знаковой арифметике одно и то же неравенство можно выразить несколькими способами: x<y, x-y<0, 0<y-x, а в беззнаковой — единственным x<y. А если слева и справа — по нескольку слагаемых/вычитаемых, то рукодельная нормализация приводит к плохо читаемому коду.

Способ 'x-y' в общем случае так же неприменим к знаковым типам, как непирименим к беззнаковым.

Отдельно, кстати, стоит заметить, что, несмотря на то, что большая часть машинных арифметических операций на популярных арихитектурах не требуют различения знаковых и беззнаковых типов, такие требования языков С/С++, как округление у нулю при целочисленном делении, зачастую таки приводят к генерации менее эффективного кода для знаковых типов. Для беззнакового типа, например, деление на 2 эквивалентно сдвигу на 1 бит вправо, а вот со знаковым типом в дополнительном коде приходится возиться дополнительно.
Best regards,
Андрей Тарасевич
Re[8]: Не! проще таки лучше!
От: Erop Россия  
Дата: 13.11.06 17:49
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Не надо фиксироваться на частностях. Мои примеры — лишь иллюстрация общего принципа. Приведенный мною ранее пример доступа с помощью указателя (или итератора) производит честный последовательный доступ к элементам контейнера. Ты же в своем примере эмулируешь последовательный доступ при помощи произвольного доступа. В общем случае это, разумеется, невозможно. И никакой оптимизирующий компиялтор тут тебе не поможет.


Ты сейчас, ИМХО, находишься в плену идеологических абстракций. На мой взгляд, опять же, вредных, так как они ведут к запутыванию кода.
Тебе надо написать пример похожего на цикл для массива, цикла для списка, который тоже успешно реализует полседовательный досутп?

Много довольно лет жили не тужили во многих языках, где вообще никакого unsigned типа не было и всё было и них хорошо.
Что такого страшного случилось после разработки STL, что коллекции стало трудно итерировать старыми добрыми простыми и надёжными способами?


Чтобы было понятнее о чём это я, вот тебе два примера последовательного доступа:

вот тебе список:
not_std::list<my_struct> lst;
for( my_struct* current = lst.last(); current != 0; current = current->prev() )
{
    // тут что-то делают с current
}


А вот и файл:
while( !is_EOF( src ) {
    char buffer[bufer_size];
    int read_count = fread( src, buffer, buffer_size );
    assert( read_count > 0 );
    // тут обрабатываем read_count байт данных из buffer
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Не! проще таки лучше!
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 18:11
Оценка:
Здравствуйте, Erop, Вы писали:

АТ>>Не надо фиксироваться на частностях. Мои примеры — лишь иллюстрация общего принципа. Приведенный мною ранее пример доступа с помощью указателя (или итератора) производит честный последовательный доступ к элементам контейнера. Ты же в своем примере эмулируешь последовательный доступ при помощи произвольного доступа. В общем случае это, разумеется, невозможно. И никакой оптимизирующий компиялтор тут тебе не поможет.


E>Ты сейчас, ИМХО, находишься в плену идеологических абстракций. На мой взгляд, опять же, вредных, так как они ведут к запутыванию кода.


Абстракции ведут к consistency (единообразию?) — основному (если не единственному) средству НЕзапутывания кода. Непонятно только, почему именно "идеологических"...

E>Тебе надо написать пример похожего на цикл для массива, цикла для списка, который тоже успешно реализует полседовательный досутп?


Не совсем понимаю, причем здесь пример для списка, если речь шла именно о массиве.

E>Много довольно лет жили не тужили во многих языках, где вообще никакого unsigned типа не было и всё было и них хорошо.


Ну так когда-то и языков никаких не было. И тоже, вроде, жили.

E>Что такого страшного случилось после разработки STL, что коллекции стало трудно итерировать старыми добрыми простыми и надёжными способами?


Во-первых, в STL — это необходимость реализации именно абстракций. Поэтому стали пользоваться новыми добрыми простыми и надёжными способами. И они, похоже, даже добрее, проще и недежней. Что делает осмысленным из использование и за пределами STL.

Во-вторых, к STL все это отностся на самом деле мало. Эти "абстакции" зарыты намного глубже.

(Причины приведения примеров не совсем понятны).
Best regards,
Андрей Тарасевич
Re[3]: А может пусть лучше оптимизатор сокращает?
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 18:14
Оценка: 1 (1) +1 :)
Здравствуйте, Erop, Вы писали:

Конечно, лучше! Вот только где бы найти такой оптимизатор... Т.е. ясно, что нет такого оптимизатора и быть не может, но все равно — лучше бы он...
Best regards,
Андрей Тарасевич
Re[6]: Нужен ли unsigned
От: Centaur Россия  
Дата: 13.11.06 18:14
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Отдельно, кстати, стоит заметить, что, несмотря на то, что большая часть машинных арифметических операций на популярных арихитектурах не требуют различения знаковых и беззнаковых типов, такие требования языков С/С++, как округление у нулю при целочисленном делении, зачастую таки приводят к генерации менее эффективного кода для знаковых типов.


В C++ такого требования в общем случае нет. Оно есть для положительных делимого и делителя; в противном случае поведение implementation-defined (C++03 5.6/4). В C — да, округление к нулю (C99 6.5.5/6).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.