sonycman 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба 1. sizeof() возвращает size_t, независимо от значения. 2. int/size_t возвращает size_t. (при условии sizeof(int) == sizeof(size_t) ) Это требование стандарта. Вы считаете, что несоблюдение компилятором стандарта языка говорит о том, что этот компилятор "более продвинутый"? :) Кстати, есть вариант, что в этих продвинутых компиляторах int просто длиннее, чем size_t, и поэтому всё получается нормально без нарушения стандарта. А что, Вы будете спорить, что IAR и прочие коммерческие компилеры - более продвинутые? Это видно и на моём примере :) А в защиту GCC можно сказать только - что он "блюдёт" стандарты. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба Вот уж не ожидал, что приведённое мной объяснение может вызвать такую реакцию. Подумайте ещё вот о чём. Существует ненулевая вероятность, что в какой-то из следующих версий IAR данное несоответствие стандарту устранят... :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба Вот уж не ожидал, что приведённое мной объяснение может вызвать такую реакцию. Подумайте ещё вот о чём. Существует ненулевая вероятность, что в какой-то из следующих версий IAR данное несоответствие стандарту устранят... :) Да обычная реакция. Когда в очередной раз слышишь, что маразм из разряда -2/1=2 - это стандарт. Не только IAR "игнорирует" ваш стандарт, но и CodeVisionAVR. Я еще Keil не проверял, возможно, он тоже из разряда "недоделанных" :) Может быть, отличия в результатах компиляции - вовсе не различная трактовка стандартов, а работа оптимизации? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба Это не мой стандарт, это стандарт языка Си. И лучше такой стандарт, чем никакого. Странно, что вы, вроде бы достаточно опытный разработчик, этого не понимаете. А уж ссылки на CodeVisionAVR - это вообще нонсенс, поскольку давно известно, что CodeVisionAVR - это компилятор "языка, похожего на Си":) Вы лучше проверьте "взрослые" компиляторы. (И посмотрите в IAR, чему там равны sizeof(int) и sizeof(size_t), вдруг и IAR соблюдает стандарт). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба (И посмотрите в IAR, чему там равны sizeof(int) и sizeof(size_t), вдруг и IAR соблюдает стандарт). Оба равны двум, что неудивительно. Только у одного 2+2 равно 4, а у второго - 5. Думаете, какой из них больше соблюдает стандарт? ЗЫ: сейчас докачаю Кейл и проверю там, на АРМ. ЗЗЫ: Упс, обновил AtmelStudio на последнюю версию 6.1 (стояла 6.0), ничего в тексте не менял, пересобрал проект - появилось знаковое деление и обработка отрицательных значений. То есть исправили багу и теперь поведение GCC стало аналогичным IAR. Попробуйте теперь объяснить, как необходимо правильно трактовать разные умные стандарты :laughing: Ставить Кейл пока не стану, уверен, что его код будет аналогичен IAR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Оба равны двум, что неудивительно. Да всяко бывает. Бывает 4 (на АРМ-ах). Бывает и 8 (на 64-битных системах). Ещё бывает, что размер int и size_t разный. Только у одного 2+2 равно 4, а у второго - 5. Думаете, какой из них больше соблюдает стандарт? Больше соблюдает тот, у которого результат соответствует стандарту. Если по стандарту должно получиться 5, то второй :) ЗЗЫ: Упс, обновил AtmelStudio на последнюю версию 6.1 (стояла 6.0), ничего в тексте не менял, пересобрал проект - появилось знаковое деление и обработка отрицательных значений. То есть исправили багу и теперь поведение GCC стало аналогичным IAR. Попробуйте теперь объяснить, как необходимо правильно трактовать разные умные стандарты :laughing: Очень рад за вас :) Не знаю, почему так. Возможно, здесь константа вычисляется во время компиляции, и поэтому она трактуется как нетипизированная. Для интереса попробуйте написать функцию, которая возвращает size_t, и поделить int на результат этой функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Прошу прощения, поторопился я вчера с выводами, поздно было, допустил невнимательность и рано обрадовался :( Не заметил приведение типов - нет, версия студии 6.1 всё так же остаётся верна стандартам и сама себе - знак так же отбрасывается, как и раньше. Зато потестил Кейл - как и предполагал, работает по аналогии с IAR - чихает на стандарты, делит со знаком и его дальнейшей обработкой. Наш человек :) Подставлял в IAR вместо sizeof() переменную с типом size_t - без разницы, никакого превращения Int в беззнаковый тип не происходит, всё работает как и раньше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zhevak 0 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Да. Было бы любопытно посмотреть на распечатку ассеблерного кода в том и другом случае. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Да. Было бы любопытно посмотреть на распечатку ассеблерного кода в том и другом случае. Вы про IAR? Уточните, пожалуйста. Смогу предоставить ассемлерный листинг только ночью или завтра, к сожалению. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zhevak 0 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Вы про IAR? Уточните, пожалуйста. Смогу предоставить ассемлерный листинг только ночью или завтра, к сожалению. Честно говоря, я не думал про какой-то конкретный компилятор. Я под Линем сижу, могу притащить сюда листин от gcc. (Если кто-нибудь меня не опередит к этому времени, гы-гы!) Давайте какой-нибудь простенький код обуликуем, откомпилируем и сравним. Внимание нужно будет уделить именно арифметическим командам проца, которые как раз занимаются вычислением деления int на size_t. Ну что, попробуем сделать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Без проблем, только я сейчас на работе, и смогу добраться до компа только к ночи, и то не надолго. Думаете, стоит расмотреть только деление, или пройтись по остальным операциям? Хотя разницы не будет, вероятнее всего. Постараюсь привести пример с делением и его код из под трех компиляторов - GCC, IAR и Keil. Последний под ARM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Коллеги , а давайте в отдельной теме. Эта всё таки про студию Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 8 ноября, 2013 Опубликовано 8 ноября, 2013 · Жалоба Коллеги , а давайте в отдельной теме. Эта всё таки про студию Разделил. Модератор Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 9 ноября, 2013 Опубликовано 9 ноября, 2013 · Жалоба Несколько устав уже от нюансов по поводу интерпретации стандатров различными компиляторами, нашёл всё таки время "добить" код, прогнав его через IAR и Keil. Результаты не совсем однозначные, но вот они, какие есть. Исходный код: volatile int tbuf[20], result; while (1) { int t = 0; for (unsigned char c = 0; c < sizeof(tbuf)/sizeof(int); c++) { t += tbuf[c]; } t /= sizeof(tbuf)/sizeof(int); //деление INT на SIZE_T, приводящее к "тихой" ошибке result = t < 0 ? t/5 : t; } Генерируется он на всех трёх компиляторах тихо, без ошибок и предупреждений, хотя несёт в себе ошибку, превращающую INT при делении в беззнаковый тип, отбрасывая таким образом все отрицательные значения. При этом GCC полностью удаляет из полученного кода часть, которая обрабатывает отрицательный результат. В IAR и Keil она присутствует, хотя выполнена может быть далеко не всегда. Полученный код на GCC (Atmel Studio 6.1): 6a: 60 e0 ldi r22, 0x00 ; 0 6c: 70 e0 ldi r23, 0x00 ; 0 6e: 80 e0 ldi r24, 0x00 ; 0 70: 90 e0 ldi r25, 0x00 ; 0 72: fb 01 movw r30, r22 74: ee 0f add r30, r30 76: ff 1f adc r31, r31 78: 21 e0 ldi r18, 0x01 ; 1 7a: 30 e0 ldi r19, 0x00 ; 0 7c: 2c 0f add r18, r28 7e: 3d 1f adc r19, r29 80: e2 0f add r30, r18 82: f3 1f adc r31, r19 84: 20 81 ld r18, Z 86: 31 81 ldd r19, Z+1 ; 0x01 88: 82 0f add r24, r18 8a: 93 1f adc r25, r19 8c: 6f 5f subi r22, 0xFF ; 255 8e: 7f 4f sbci r23, 0xFF ; 255 90: 64 31 cpi r22, 0x14 ; 20 92: 71 05 cpc r23, r1 94: 71 f7 brne .-36 ; 0x72 <main+0x1c> 96: 03 d0 rcall .+6 ; 0x9e <__udivmodhi4> 98: 7a a7 std Y+42, r23 ; 0x2a 9a: 69 a7 std Y+41, r22 ; 0x29 9c: e6 cf rjmp .-52 ; 0x6a <main+0x14> Код IAR (v6.21): \ ??main_1: \ 00000004 E045 LDI R20, 5 \ 00000006 E050 LDI R21, 0 \ 00000008 .... RCALL ?SS_DIVMOD_L02 \ ??main_2: \ 0000000A 8308 ST Y, R16 \ 0000000C 8319 STD Y+1, R17 \ ??main_0: \ 0000000E E000 LDI R16, 0 \ 00000010 E010 LDI R17, 0 \ 00000012 E020 LDI R18, 0 \ ??main_3: \ 00000014 2FEC MOV R30, R28 \ 00000016 5FEE SUBI R30, 254 \ 00000018 2F32 MOV R19, R18 \ 0000001A 0F33 LSL R19 \ 0000001C 0FE3 ADD R30, R19 \ 0000001E 8140 LD R20, Z \ 00000020 8151 LDD R21, Z+1 \ 00000022 0F04 ADD R16, R20 \ 00000024 1F15 ADC R17, R21 \ 00000026 9523 INC R18 \ 00000028 3124 CPI R18, 20 \ 0000002A F3A0 BRCS ??main_3 \ 0000002C E144 LDI R20, 20 \ 0000002E E050 LDI R21, 0 \ 00000030 .... RCALL ?SS_DIVMOD_L02 \ 00000032 2311 TST R17 \ 00000034 F33A BRMI ??main_1 \ 00000036 CFE9 RJMP ??main_2 Здесь уже ошибки нет, применяется деление со знаком. Однако, если скомпилировать не Release код, а Debug, при тех же настройках оптимизации, получается код с беззнаковым делением. Интересно :05: Кейл (uVision v4.72) тоже применяет деление без знака, как и GCC, хотя мне вначале казалось наоборот. Прошу простить за невнимательность :smile3046: 00000c 2314 MOVS r3,#0x14 00000e 466a MOV r2,sp ;33 ;;;37 ;;;38 result = t < 0 ? t/5 : t; 000010 2405 MOVS r4,#5 |L1.18| 000012 2100 MOVS r1,#0 ;30 000014 ea4f0001 MOV.W r0,r1 ;31 |L1.24| 000018 f8525020 LDR r5,[r2,r0,LSL #2] ;33 00001c 1c40 ADDS r0,r0,#1 ;31 00001e 4429 ADD r1,r1,r5 ;33 000020 2814 CMP r0,#0x14 ;31 000022 d3f9 BCC |L1.24| 000024 fbb1f0f3 UDIV r0,r1,r3 ;36 000028 2800 CMP r0,#0 00002a da01 BGE |L1.48| 00002c fb90f0f4 SDIV r0,r0,r4 |L1.48| ;;;39 ;;;40 } 000030 9014 STR r0,[sp,#0x50] 000032 e7ee B |L1.18| Логика несколько неясна, после UDIV проверять значение на отрицательный знак? Это возможно разве? Но не перестаю восхищаться красивым, мощным, ёмким и компактным кодом Cortex ARM. Он в два раза короче, чем код для AVR! :disco: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maksimp 0 28 ноября, 2013 Опубликовано 28 ноября, 2013 · Жалоба При этом GCC полностью удаляет из полученного кода часть, которая обрабатывает отрицательный результат. Чудеса оптимизации. Умеет определять, что после деления 0...65535 на 20 получится 0...3276, после преобразования к знаковому будет не отрицательным у ветка для t<0 не нужна. Код IAR (v6.21): ... Здесь уже ошибки нет, применяется деление со знаком. Однако, если скомпилировать не Release код, а Debug, при тех же настройках оптимизации, получается код с беззнаковым делением. Интересно :05: Увы, IAR не вызывает доверия. Самый худший вариант, когда результат зависит от включения отладки :(. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться