Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 23-08-2007 08:29 » |
|
(в VC++6) простенький пример BYTE b='а';//русская буква const BYTE* p=&b;
if(p[0]=='а') { int iii=1;//сюда почему то не переходим (?????) }
а вот так if(p[0]==(BYTE)'а')
уже правильно переход совершается. Замечено с русскими буквами, с цифрами и латиницей всё нормально и без (BYTE) работает так вот - кто глючит , я или студия ?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 23-08-2007 08:37 » |
|
разница в коде if( p[0]==(BYTE)'з') 0040B135 mov edx,dword ptr [ebp-8] 0040B138 xor eax,eax 0040B13A mov al,byte ptr [edx] 0040B13C cmp eax,0E7h 0040B141 jne xxxx+0E4h (0040b194)
if( p[0]=='з') 0040B135 mov edx,dword ptr [ebp-8] 0040B138 xor eax,eax 0040B13A mov al,byte ptr [edx] 0040B13C cmp eax,0E7h 0040B13F jne xxxx+0E5h (0040b195)
то есть разницы никакой ))) Кроме неправильного перехода
|
|
« Последнее редактирование: 23-08-2007 08:39 от Алексей1153++ »
|
Записан
|
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #3 : 23-08-2007 11:37 » |
|
а фик знает... опции такие /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FR"Debug/" /Fp"Debug/FanEngine.pch" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
где тут что, я не знаю, не разбирадлся никогда ) или где надо поглядеть ?
|
|
|
Записан
|
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 23-08-2007 17:34 » |
|
у мну в студии нет таких настроек... Либо я не могу найти
самое смешное и непонятное ведь вот в чём: сравнение компилятор делает в обоих случаях одинаково, с нужным числом ('з'==0xE7). А адрес перехода различается. Следовательно, юникод ни при чём, а то бы он сравнивал со словом, а не байтом
|
|
« Последнее редактирование: 23-08-2007 17:37 от Алексей1153++ »
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #6 : 23-08-2007 21:16 » |
|
Алексей1153++, Byte это unsigned char. Просто 'a' это signed char в Visual Studio C++6.0 Отсюда вся и пляска с бубном. Я первый раз с этим столкнулся, когда пытался работать с массивом. В качестве индекса выступали символы с текста
|
|
« Последнее редактирование: 23-08-2007 21:18 от Finch »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 24-08-2007 03:36 » |
|
ясно... буду теперь знать грабли ))
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #8 : 24-08-2007 03:40 » |
|
только всё же непонятный момент - почему ассемблерный код одинаковый, кроме перехода , ведь однин из сравниваемых аргументов - переменная, тогда откуда компилятор выяснил, что равенство не будет выполнено ? Или он сразу по несовпадению типов решил в обход пойти ?
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #9 : 24-08-2007 13:24 » |
|
Лёш, там скорее всего еше есть код, относяшийся к условию. Теперь о другом. Заметь, у тебя сравнивается с регистром eax. Этот регистр 32 разрядный. Значит Все отрицательные числа, записанные в байт и заполненные в eax изначально будут больще всех положительных чисел.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 24-08-2007 14:23 » |
|
Finch, ты не прав //загрузили проверяемый байт в младший байт регистра eax, //а старшие байты обнулены 0040B138 xor eax,eax 0040B13A mov al,byte ptr [edx] //сравниваем с числом 0x000000e7 , 3 старшие байта также нулю равны 0040B13C cmp eax,0E7h знак в этом случае ни при чём вижу объяснение такое: компилятор видит, что константа 'з' - "отрицательная". Также он видит, что тип unsigned (заведомо "положительный") сравнивается с отрицательным числом. То есть , по его,компилятора, мнению, результат всегда false
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #11 : 28-08-2007 06:09 » |
|
Да, есть такие грабли. Вот простой пример: #include <stdio.h>
int main(void) { char a = (char)0xe9; unsigned char b = 0xe9;
if( a == b ) printf("OK\n"); else printf("ERR\n");
return 0; } который выводит "ERR". А вот что сгенерировал компилятор: _TEXT SEGMENT _a$ = -4 _b$ = -8 _main PROC NEAR ; COMDAT
; 4 : {
push ebp mov ebp, esp sub esp, 72 ; 00000048H push ebx push esi push edi lea edi, DWORD PTR [ebp-72] mov ecx, 18 ; 00000012H mov eax, -858993460 ; ccccccccH rep stosd
/* * Вот здесь показано как компилятор воспринял значение 0xe9 * для типа "char". */ ; 5 : char a = (char)0xe9; mov BYTE PTR _a$[ebp], -23 ; ffffffe9H /* грабли номер 1 */
/* * А здесь для типа "unsigned char". */ ; 6 : unsigned char b = 0xe9; mov BYTE PTR _b$[ebp], 233 ; 000000e9H
; 7 : ; 8 : if( a == b ) printf("OK\n");
/* * А вот самые главные грабли. Идет загрузка byte с расширением по * знаку в "eax" и мы получаем 0xffffffe9. */ movsx eax, BYTE PTR _a$[ebp]
/* * Здесь все нормально, только странно както. Загружает слово в "ecx", * а потом выделяет в нем регистр "cl". * Можно было бы и одной командой обойтись: "movzbl -8(%ebp), %ecx" */ mov ecx, DWORD PTR _b$[ebp] and ecx, 255 ; 000000ffH
/* * Ну а здесь, результат и так понятен. */ cmp eax, ecx jne SHORT $L341 push OFFSET FLAT:??_C@_03IOOG@OK?6?$AA@ ; `string' call _printf add esp, 4
; 9 : else printf("ERR\n");
jmp SHORT $L343 $L341: push OFFSET FLAT:??_C@_04ILN@ERR?6?$AA@ ; `string' call _printf add esp, 4 $L343:
; 10 : ; 11 : return 0;
xor eax, eax
; 12 : }
pop edi pop esi pop ebx add esp, 72 ; 00000048H cmp ebp, esp call __chkesp mov esp, ebp pop ebp ret 0 _main ENDP _TEXT ENDS
|
|
« Последнее редактирование: 28-08-2007 06:28 от Serg79 »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #12 : 28-08-2007 07:43 » |
|
Serg79, в твоём асме явно видно, что используется знак, согласен. А в примерах из моего поста - знак не компилчтор явно не применил...
|
|
|
Записан
|
|
|
|
|