Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.05.08;
Скачать: [xml.tar.bz2];

Вниз

Почему допустимо integer(<адрес в памяти>) ?   Найти похожие ветки 

 
Anatoly Podgoretsky   (2003-04-16 16:41) [40]

А что бы от такого не зависить, раз уж мы условилиль, что у нас это является указателем, то надо использовать BYTE.
И в реальной жизни, вместо Integer - LongWord/Cardinal


 
Giemgo   (2003-04-16 18:31) [41]

1) Опять вы меня не допоняли... ;(

10000000b
+
00000001b
-----------
10000001b

вот так физически (и никак по иному !!!) происходит сложение двух операндов в ходе исполнения процессором маш.инструкции . Хоть "со знаком" операнды, хоть "без знака" )

Это понятно ? Не вызывает вопросов ?


Это-то вопросов не вызывает. А вот вызывает вопросы такое:

01111111b
+
00000001b

Ну как такое для shortint может пройти ? Получается что 127+1=-128 ахинея какая-то

2) Вот тут подумалось. А что, если сложить (-1)+(-1)

11111111b
+
11111111b
---------

должно получится (-2), то есть:

11111110b Но по логике получается:
111111110b


 
Anatoly Podgoretsky   (2003-04-16 18:46) [42]

Не надо считать адреса числами, тем более со знаком!

1. Ахинея точно, но только у тебя, указатель это не число
127+1=128 (адрес со смещением 128)

2. Переполнение адресной сетки
254+254=508 при размере адресной сетки 255


 
Serginio   (2003-04-16 19:22) [43]

Мне конечно нравится ваша полемика. Может конечно ошибаться, но
вторая полвина адресов 4ГБ пространства отдана для системных адресов виндов.Так что по барабану. А если учесть 64 разрядные процессоры то LongWord не правильно а Integer правильно, так как становится Int64.


 
Anatoly Podgoretsky   (2003-04-16 21:01) [44]

Serginio (16.04.03 19:22)
В истории существования процессоров Интел, не всегда ширина адреса совпадала с разрядной сеткой просцессора.
Если посмотреть

8080 8 бит 16 бит
8086-286 16 бит 20 бит
+386 16/32 20/32


Каким будет 64 битный процессор еще вопрос, кроме того надо учитывать и возможность работы на других платформах

Это примерно так как многие погорели при переходе с 16 битной среды на 32 битную, считая, что Integer равен 16 битам
Да и Pointer менялся с 16/32 бит на 32 бита.
Все это опачные трюки Integer(P), особенно что есть специальный тип, PChar для которого поддержана адресная математика P := P + I


 
Giemgo   (2003-04-16 23:07) [45]

Ахинея точно, но только у тебя, указатель это не число
127+1=128 (адрес со смещением 128)


Блин. Указатель - это не число, ну и чего ?!

(Integer(P)+1 тут то будут СКЛАДЫВАТЬСЯ ЧИСЛА.

--------------------------------------------------

УРА ! Аллилуя ! Разобрался. За что спасибо evvcom © (16.04.03 15:46)

Все таки оказалось по моему.
p:=Pointer(Integer(P)+1) это не корректно. Нужно применять LongWord.

Для демонстрации ошибки можно применить такой код.

procedure TForm1.Button1Click(Sender: TObject);
var P:Pointer;
begin
p:=Pointer($7FFFFFFF);
p:=Pointer(Integer(P)+1):
// Какой-то код
end;

Ведь может быть такой адрес в памяти, как $7FFFFFFF ? Может, конечно ! А если я хочу узнать адрес следующего байта памяти ?
Хоть тут и говорили, что использование integer"а не несет угрозы, но ведь несет !
Если я как показано выше сделаю и у меня установлен флажок в опциях проекта Overflow checking, то вылезет exeption ! И соответственно последующий код НЕ выполнится ! А если использовать LongWord все ок !

Конечно, по умолчанию этот флажок Overflow checking не стоит. И как я уже отмечал обращения к таким адресам памяти как $7FFFFFFF маловероятны, но существование проблемы налицо !!!

О чем я и догадывался, начиная эту ветку. Теперь разобрался. Всем спасибо.


P.S. Уже не в тему, но коли мы затронули побитовые операции.

Не понимаю как складываются отрицательные числа.
Допустим: (-1)+(-1)

11111111
+
11111111
----------
?

По идее, -2 получится. Но если побитово складывать, получится переполнение... странно...


 
default   (2003-04-16 23:31) [46]

procedure TForm1.Button1Click(Sender: TObject);
var
P: Pointer;
begin

P := Pointer($7FFFFFFF); // начальный адрес: $7FFFFFFF
Caption := IntToStr(LongWord(P));
P := Pointer(Integer(P) + 1); // конечный адрес $8FFFFFFF
Caption := Caption + " : " + IntToStr(LongWord(P));

end;


нифига ты непонял
смотри код выше
скажи ты всегда всё догоняешь(типа) с 20 раза да ещё и не верно?


 
default   (2003-04-16 23:39) [47]

procedure TForm1.Button1Click(Sender: TObject);
var
i: LongWord;
P: Pointer;
begin

Caption := "Ты не прав";
for i := 0 to $FFFFFFFF do begin
P := Pointer(i);
if Pointer(Integer(P) + 1) <> Pointer(LongWord(P) + 1) then begin
Caption := "Я не прав";
Break;
end;
end;

end;

если ты уж до такой степени твердолобый этот код УБЕДИТ тебя что ты НЕ ПРАВ!


 
Giemgo   (2003-04-16 23:57) [48]

default, ха ха. А ты мой пост Giemgo (16.04.03 23:07) читал ? Если читал - то мне тебя очень жаль


 
default   (2003-04-17 01:58) [49]

Giemgo
и что ?
мне кажется ты тупишь с переполнением
завтра лично проверю
но это значения не имеет никакого смотри (16.04.03 23:39)


 
default   (2003-04-17 02:21) [50]

procedure TForm1.Button1Click(Sender: TObject);
var
P1, P2: Pointer;
begin

Integer(P1) := Integer(3000000000);
LongWord(P2) := LongWord(3000000000);
if P1 = P2 then ShowMessage("Ну ты дурак редкий! P.S. Достал просто.")

end;


вот этот код и с твоим флажком будет работать...а жалеть надо ламмеров ха ха ха
неужели догнать не можешь?
был бы поумней сначало изучил как числа со знаком в компе представляются а
потом бы вопрос на форум кидал...не надо валить с больной головы на здоровую


 
А123   (2003-04-17 04:40) [51]

2Giemgo (16.04.03 23:07)

>Не понимаю как складываются отрицательные числа.
>Допустим: (-1)+(-1)

>11111111
>+
>11111111
----------
>?

>По идее, -2 получится. Но если побитово складывать, получится >переполнение... странно...

У тебя слишком "боязненное" отношение к переполнению. Переполнение - не есть ошибка, в каком либо виде. Это лишь приводит к установке флагов процессора, как уже указал Digitman. А вот учитывать (или не учитывать) эти флаги в последующих инструкциях - это задача или компилятора (если программа на Дельфи) или твоя (если пишешь на ассемблере).


 
Sha   (2003-04-17 09:07) [52]

Как уже писал Anatoly Podgoretsky © (15.04.03 22:31)
для сложения целых чисел размером до 32 бит в процессоре используется одна единстственная команда ADD.
При сложениии одинаковых битов будет получен одинаковый (в битовом выражении) результат.
А как этот результат потом интерпретировать (integer, cardinal) - не имеет значения. Все равно при обратном кастинге типа вы получите тот же самое значение (т.к. битовое выражение не изменилось).



 
Palladin   (2003-04-17 09:41) [53]

какой трудный "ученик" попался...
неужели трудно почитать булеву алгебру, дискретную математику и пр., чем мучить народ такой "сложной" проблемой?


 
Anatoly Podgoretsky   (2003-04-17 09:44) [54]

Так Юрий Зотов специально организовал уроки для начинающем на этом сайте, где данный вопрос представления чисел в процессорах и выполнения операций над ним также рассмотрен.


 
Giemgo   (2003-04-17 12:37) [55]

default © (17.04.03 02:21)

Ну ты даааааал. Если сам не понимаешь о чем я тут говорю - так и не лезь. Разберись, пожалуйста, САМ. Как разобрался я. А потом советуй.

for i := 0 to $FFFFFFFF

Вот за это тебе надо вообще руки поотрывать. А еще это говорит о том, что ты абсолютно не владеешь знаниями по теме. И к тому же не читаешь предупреждения компилятора. А он ясно говорит тебе, что удалил код цикла, так как цикл бесконечный.

Если ты хочешь все таки разобраться как и я, ОТВЕТЬ НА ВОПРОС:

procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
p:Pointer;
begin
{$Q-}
Caption := "Ты не прав";
i:=$7FFFFFFF;
P:=Pointer(integer(i)+1);
if P<>nil then Caption:="Я не прав";
{$Q+}
end;

Внимательно проанализируй каждую строчку кода и подумай. А почему это в конце операции форма имеет заголовок "Ты не прав" ?

Внимание ! Вопрос только для default. Пусть он напишет ответ.

--------------------------------------------------

А у меня ко всем остальным вопрос:

-1 это 11111111b ?
А 11111111b это $FF

Тогда почему не работает:

var i:shortint;
...
i:=$FF

?


 
Palladin   (2003-04-17 12:46) [56]


> Тогда почему не работает:

потому что это проверка на дурака на уровне компилятора...
i:=shortint($ff) или
byte(i):=$ff;

этим ты закроешь глаза компилятору...


 
Palladin   (2003-04-17 12:52) [57]

тьфу :)
защита от дурака всмысле

и кстати "не компилируется" и "не работает" два разных выражения...


 
default   (2003-04-17 17:06) [58]

Удалено модератором
Примечание: Воздерживайся от личных оскрблений


 
Sandman25   (2003-04-17 18:27) [59]

"for i := 0 to $FFFFFFFF do" приводит не к бесконечному циклу, а наоборот, к невыполняемому ни разу (поэтому компилятор и удаляет цикл). Для захода в цикл нужно писать "for i := $FFFFFFFF to 0 do". Без шуток.


 
Anatoly Podgoretsky   (2003-04-17 18:39) [60]

Это зависит от типа i
Integer, выполнится два раза
Int64, Cardinal (начиная с версии 3 или выше, до этого диапазон был в два раза меньше), выполнится 2^32 раз


 
default   (2003-04-17 18:48) [61]

procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
p:Pointer;
begin
{$Q-}
Caption := "Ты не прав";
i:=$7FFFFFFF;
P:=Pointer(integer(i)+LongWord(1));
if P<>nil then Caption:="Я не прав";
{$Q+}
end;
пиши так если боишься за переполнение которое очень
маловероятно
предыдущее сообщение было удалено поэтому лень повторяться
что было то было



 
Anatoly Podgoretsky   (2003-04-17 18:53) [62]

Приношу прощение только сейчас заметил, для Integer 0 раз, поскольку от 0 до -1, в голове местами операнды поменял :-(


 
Giemgo   (2003-04-17 19:10) [63]

default, не знаю, что ты там мне написал, но ты не сердись. Я тебя обидеть не хотел, просто указал, что тебе нелишне будет самому поразбираться в теме или повнимательнее почитать мои посты.

если ты уж до такой степени твердолобый этот код УБЕДИТ тебя что ты НЕ ПРАВ!

Слушай, твои наезды просто беспочвенны. Данный тобой код меня ни в чем не убедит, так как он полностью неправильный. И вообще, если бы даже цикл был составлен правильно, что из этого ? Я не говорил, что условие "Pointer(Integer(P) + 1) <> Pointer(LongWord(P)" когда-нибудь выполнится. Я говорил про переполнение.

В своем посте Giemgo (17.04.03 12:37) я задал тебе вопрос, ответь на него, пожалуйста, даже если ответ тебе очевиден


Anatoly Podgoretsky © (17.04.03 18:39)
Это зависит от типа i
Integer, выполнится два раза
Int64, Cardinal (начиная с версии 3 или выше, до этого диапазон был в два раза меньше), выполнится 2^32 раз


Анатолий, а это вы про что ?


 
Palladin   (2003-04-17 19:43) [64]

про то что если i:integer, то цикл выполнится 2 раза....
если i:int64 или i:cardinal, то цикл выполнится 4294967296 раз


 
default   (2003-04-17 20:13) [65]

я уже говорил про переполнение
i := $7FFFFFFF
в Pointer(integer(i)+1); // получается что MaxInt + 1 > MaxInt
если тебе этого так хотелось
чтобы его никогда не было
Pointer(integer(i)+LongWord(1));
or
Pointer(LongWord(i)+1);
но этот момент почти никакого отношения не имеет к первоначальному вопросу в нём другая фишка была
про которую писал Sha и многие другие...



 
Anatoly Podgoretsky   (2003-04-17 20:35) [66]

Giemgo (17.04.03 19:10)
Anatoly Podgoretsky © (17.04.03 18:39)
Это зависит от типа i
Integer, выполнится два раза

Palladin © (17.04.03 19:43)

Я уже поправился - 0 раз
Остальное правильно.


 
Giemgo   (2003-04-17 20:45) [67]

Повторю мой вопрос: складываем два однобайтовых числа отрицательных.

11111111b
+
11111111b
---------
?

Должно получится -2. Но если складывать побитово столбиком, то, по идее, возникнет переполнение !
Так почему здесь компилятор не сообщает о переполнении ?

Если написать

var i:shortint;
...
i:=127;
i:=i+1

то компилятор выдаст Integer Overflow, так как переполнение.

Ну а ведь как я показывал выше (-1)+(-1) тоже переполнение дает! Но компилятор уже не сообщает почему то.


 
Palladin   (2003-04-17 20:54) [68]

хм я тоже ошипся... :)
2 раза выполнится
for i:=integer($ffffffff) to 0
в общем это уже оффтопик пошол...


> Giemgo (17.04.03 19:10)

извини но я не понимаю в чем вы тут с default спорите...
повторю тебе уже наверно четвертый или пятый раз,
ложки не существует (С) матрикс
нет ни целого числа, ни знакового. есть набор бит. как хочешь так его и представляй. и как ты его представишь, так компилятор и отработает с ним: по правилам представления.


 
Anatoly Podgoretsky   (2003-04-17 20:54) [69]

-1 + -1 равно двум, никакого переолнения нет. Идея не верная.
127 + 1 равно 128, вот сдесь переполнение.


 
Anatoly Podgoretsky   (2003-04-17 20:55) [70]

-2 конечно


 
Giemgo   (2003-04-17 20:59) [71]

но этот момент почти никакого отношения не имеет к первоначальному вопросу в нём другая фишка была

Ух ты ! Вот блин. А о чем, по твоему, был вопрос ?! Мне это очень интересно узнать ! По моему, ты так увлекся доказательством мне чего-то посредством невыполняющихся циклов, что ушел от сути. Первоночальный вопрос читал ? Перечитай !
Собственно говоря, он о том и был. Могу процитировать, чтобы ты не скролил:

Но видел, что люди пишут, допустим, так:

integer(p)+1
...
Хотя ведь правильней LongWord(p)+1 ?


Да ? Так оно и есть ? Правильней писать LongWord ! По моему, это именно то, что ты и написал:

Pointer(integer(i)+LongWord(1));
or
Pointer(LongWord(i)+1);
пиши так если боишься за переполнение которое очень
маловероятно


Да, маловероятно, я и об этом писал. Но проблема есть. ВОТ И ВСЕ, ЧТО Я ХОТЕЛ СКАЗАТЬ.

P.S. Ты, конечно, будешь говорить, что это очевидно и и т.д. Только вот уверен, что если бы был тест при приеме на работу "Чем опасен p:=Pointer(Integer(p)+1)" ты бы не ответил. Как и я.

Потому что даже мастера тут не сразу въехали. Не говоря уж о том, что некоторые и считают неправильно :))))


 
Anatoly Podgoretsky   (2003-04-17 21:08) [72]

Правильнее PChar + 1


 
Palladin   (2003-04-17 21:13) [73]

ничем не правильней...
абсолютно одинаково и абсолютно безопасно...
а вот ты так и не допер... тебя жаль...

ЗЫ LongWord(i)+1 тоже будет переполнение при i=$ffffffff


 
default   (2003-04-17 22:18) [74]

тема уже исчерпана фиг знает сколько времени назад
Giemgo случайно заметив переполние стал "кричать" что он был прав и тд и тп
хотя начиная тему явно об этом и не догадывался
но это такой пустяк блин даже говорить о нём не хочется...
надо же так развести(это относится к Giemg-е)это надо ещё уметь зы
что меня в тебе поражает так это то что ты не изучив двоичную арифметику говоришь что
что-то там не так...странно...ууууу ааааа ха ха ха
всё через Ж делаешь
тебе же Юрий Зотов дал ссылки...ну ты видно полезную информацию игноришь пожизни
отсюда и столько вопросов!
и ещё не сочти за оскорбление но 90% твоих слов "глаголят" такую ахинею что уши вянут
серьёзно
я думаю любой подтвердит
стремление к знаниям видно но какое-то оно кривое у тебя...или мышление кривое...
вроде догоняешь но с 10-ого раза
и возвращаясь к переполнению
я до этого не знал(или забыл) что если пишешь типа Integer(1000) + 1 - компилятор
требует чтоб рез-ат этого выражения был Integer - поэтому об этом и не задумывался


 
Giemgo   (2003-04-17 23:42) [75]

ЗЫ LongWord(i)+1 тоже будет переполнение при i=$ffffffff

Это понятно. Только вот указатель тоже не может быть больше $FFFFFFFF. Так что это уж точно не проблема. А если будет переход на новую платформу - то это совсем другой разговор.

а вот ты так и не допер... тебя жаль...

Я, конечно, ламер по сравнению с тобой. Но, по моему, это ты не допер. Мне кажется на примере я ясно показал, что Integer и LongWord это не абсолютно одинаковое.
Если в одном случае возникает исключение, а в другом не возникает - это можно считать разницей, ты как считаешь то ?!

Giemgo случайно заметив переполние стал "кричать

Абсолютно не согласен. Переполнение я искал специально. Просто сразу не сообразил как сформулировать проблему. Да и после того как сформулировал меня недопонимают.

тебе же Юрий Зотов дал ссылки

Я их прочитал между прочим. И собственно говоря по их прочтении у меня и возникло подозрение насчет корректности integer(p)+1
---------------------------

Ну народ. Я вам удивляюсь. Вроде я достаточно четко объяснил, что в случает integer возникает переполнение. В случае LongWord переполнения не возникает. Я ОСОЗНАЮ, что и там и там хранятся одинаковые байты. Но из-за установки флага переполнения Дельфи при соответствующих установках компилятора генерит exeption, который может кардинально поменять результат. Я прав. Это очевидно.
-----------------------------------------------

У меня остался вопрос.

-1 + -1 равно минус двум, никакого переолнения нет. Идея не верная.
127 + 1 равно 128, вот сдесь переполнение.


То есть, как понимаю, в первом случае устанавливается флаг переноса на который Дельфи не реагирует исключением. А во втором случает устанавливается флаг переполнения на которое дельфи как раз реагирует исключением ?
Если это так - просто скажите да.

P.S. Хоть я и не понимаю недоброжелательное отношение многих к моим искренним попыткам разобраться с этой кухней и не понимаю чем я так насолил, что люди ругаются на меня. Но в любом случае прошу прощения за доставленные неудобства


 
Palladin   (2003-04-18 00:00) [76]

дык вот в чем соль то...

при приеме на работу оказывается проверяют знания галочек в настройках опций компилятора делфей :)

ладно, цель достигнута, твою мысль я понял,а ты, в свою очередь, понял что ложки нет :)

просто маленькое уточнение, про прием на работу
p:=Pointer(Integer(p)+1) абсолютно безопасен при {Q-}


 
Anatoly Podgoretsky   (2003-04-18 00:26) [77]

Есть несколько флагов в процсессоре

OV устанавливается если происходит неверная смена знака для знакоых целыч, 128 на самом деле равно -128, что неверно. Это будет переполнение для знаковых

CY - если есть перенос из старшего разряды, это будет переполнение для беззнаковых.

S - флаг знака.

Дельфи их правильно обрабатывает на основе типа числа. Процессору же все равно, не царское это дело, его дела правильно выставить флаги, а интерпритцией занимается программа.

Флаг переноса <> флагу переполнения, а ты их путаешь.

Прм сложении -1/255 (FF) с +1 (01) будет установне CY, результат 0, ошибка для беззнаковых (или перенос в следующий разряд, нормально для знаковых)
1111 1111
0000 0001
1.0000 0000

Прм сложении -1/255 (FF) с -1 (FF) будeт установлены CY, S, результат -2/254 (FE), ошибка для беззнаковых (или перенос в следующий разряд, нормально для знаковых)
1111 1111
1111 1111
1.1111 1110

Прм сложении +127 (7F) с +1 (01) будeт установлены OV, S, результат -128/128 (FE), ошибка для беззнаковых (переноса нет, нормально для знаковых)
0111 1111
0000 0001
0.1000 0000

Прм сложении -128/128 (80) с -1/255 (FF) будeт установлены CY, OV, результат 0, ошибка для беззнаковых (есть перенос, ошибка для обеих)
1000 0000
1000 0000
1.0000 0000


 
Giemgo   (2003-04-18 00:43) [78]

при приеме на работу оказывается проверяют знания галочек в настройках опций компилятора делфей :)

Не иронизируй. Если ты вдумаешься, то знание галочек компилятора это не фигня. Из-за них ты можешь долго искать ошибку, как искал я в другой своей ветке. Если ты целый день будешь искать ошибку - а она заключается в одной галке, ты будешь выглядить глупо, согласись ?
Можно также утверждать, что при приеме на работу проверяют, знаешь ли ты что Delphi объекто-ориентированный язык. Конечно, нет. Но если узнают, что ты этого не знаешь... сам понимаешь

ладно, цель достигнута, твою мысль я понял

скажи честно - ты ее только сейчас понял ? Я не про то, что ты тупой. Я про то, что может я объяснять не умею, потмоу как повторял неоднократно.

а ты, в свою очередь, понял что ложки нет

Да, конечно. Если честно, то я с первого твоего поста понял, что ложки нету. И даже открою секрет, догадывался о ее несуществовании :)))

просто маленькое уточнение

А вот тут я не очень понимаю. В спраке то написано как ты сказал.

И на самом деле такой код вызывает исключение:

{$Q+}
i:=$7FFFFFFF;
i:=i+1;

Но вот почему следующий код вызывает исключение ?

{$Q-}
i:=$7FFFFFFF;
i:=i+1;
{$Q+}


 
Palladin   (2003-04-18 00:59) [79]


> Giemgo (18.04.03 00:43)

цель достигнута первоначальная...
тебе в стало понятно почему же допустимо integer(<адрес в памяти>)
а вопрос "к каким подводным камням это может привести?" очень долго у тебя формировался, пока наконец не оформился на 70какомто посте...
давай не будем рассуждать больше, а просто ты научишься обдумывать вопрос...


 
Palladin   (2003-04-18 01:03) [80]


> Но вот почему следующий код вызывает исключение ?
>
> {$Q-}
> i:=$7FFFFFFF;
> i:=i+1;
> {$Q+}


вот такой код не вызовет исключений при любом Q
проверено

i:=$7fffffff;
p:=pointer(integer(i)+1);



Страницы: 1 2 3 вся ветка

Форум: "Основная";
Текущий архив: 2003.05.08;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.64 MB
Время: 0.012 c
14-23339
Denich
2003-04-20 01:15
2003.05.08
????Ребят, как удалять Paramstr(0)????


14-23386
down
2003-04-21 20:54
2003.05.08
посмотрите, какое красивое извращение


7-23406
~Mr.L@g~
2003-03-04 16:01
2003.05.08
Ассоциация файлов в WINDOWS


1-23170
dimonf
2003-04-24 08:43
2003.05.08
Как избавиться от стандартной прорисовки в ListBox-e???


14-23306
C3H5(OH)3
2003-04-18 11:49
2003.05.08
Диалоги в ресурсах





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский