Перейти к содержанию
    

1. sizeof() возвращает size_t, независимо от значения.

2. int/size_t возвращает size_t. (при условии sizeof(int) == sizeof(size_t) )

Это требование стандарта.

Вы считаете, что несоблюдение компилятором стандарта языка говорит о том, что этот компилятор "более продвинутый"? :)

 

Кстати, есть вариант, что в этих продвинутых компиляторах int просто длиннее, чем size_t, и поэтому всё получается нормально без нарушения стандарта.

 

А что, Вы будете спорить, что IAR и прочие коммерческие компилеры - более продвинутые?

Это видно и на моём примере :)

А в защиту GCC можно сказать только - что он "блюдёт" стандарты. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Подумайте ещё вот о чём. Существует ненулевая вероятность, что в какой-то из следующих версий IAR данное несоответствие стандарту устранят... :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Подумайте ещё вот о чём. Существует ненулевая вероятность, что в какой-то из следующих версий IAR данное несоответствие стандарту устранят... :)

Да обычная реакция. Когда в очередной раз слышишь, что маразм из разряда -2/1=2 - это стандарт.

 

Не только IAR "игнорирует" ваш стандарт, но и CodeVisionAVR.

Я еще Keil не проверял, возможно, он тоже из разряда "недоделанных" :)

 

Может быть, отличия в результатах компиляции - вовсе не различная трактовка стандартов, а работа оптимизации?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это не мой стандарт, это стандарт языка Си.

И лучше такой стандарт, чем никакого. Странно, что вы, вроде бы достаточно опытный разработчик, этого не понимаете.

А уж ссылки на CodeVisionAVR - это вообще нонсенс, поскольку давно известно, что CodeVisionAVR - это компилятор "языка, похожего на Си":)

Вы лучше проверьте "взрослые" компиляторы.

(И посмотрите в IAR, чему там равны sizeof(int) и sizeof(size_t), вдруг и IAR соблюдает стандарт).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

(И посмотрите в IAR, чему там равны sizeof(int) и sizeof(size_t), вдруг и IAR соблюдает стандарт).

Оба равны двум, что неудивительно. Только у одного 2+2 равно 4, а у второго - 5.

Думаете, какой из них больше соблюдает стандарт?

 

ЗЫ: сейчас докачаю Кейл и проверю там, на АРМ.

 

ЗЗЫ: Упс, обновил AtmelStudio на последнюю версию 6.1 (стояла 6.0), ничего в тексте не менял, пересобрал проект - появилось знаковое деление и обработка отрицательных значений.

То есть исправили багу и теперь поведение GCC стало аналогичным IAR.

Попробуйте теперь объяснить, как необходимо правильно трактовать разные умные стандарты :laughing:

 

Ставить Кейл пока не стану, уверен, что его код будет аналогичен IAR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оба равны двум, что неудивительно.

Да всяко бывает. Бывает 4 (на АРМ-ах). Бывает и 8 (на 64-битных системах). Ещё бывает, что размер int и size_t разный.

Только у одного 2+2 равно 4, а у второго - 5. Думаете, какой из них больше соблюдает стандарт?

Больше соблюдает тот, у которого результат соответствует стандарту. Если по стандарту должно получиться 5, то второй :)

ЗЗЫ: Упс, обновил AtmelStudio на последнюю версию 6.1 (стояла 6.0), ничего в тексте не менял, пересобрал проект - появилось знаковое деление и обработка отрицательных значений.

То есть исправили багу и теперь поведение GCC стало аналогичным IAR.

Попробуйте теперь объяснить, как необходимо правильно трактовать разные умные стандарты :laughing:

Очень рад за вас :)

Не знаю, почему так. Возможно, здесь константа вычисляется во время компиляции, и поэтому она трактуется как нетипизированная.

Для интереса попробуйте написать функцию, которая возвращает size_t, и поделить int на результат этой функции.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прошу прощения, поторопился я вчера с выводами, поздно было, допустил невнимательность и рано обрадовался :(

Не заметил приведение типов - нет, версия студии 6.1 всё так же остаётся верна стандартам и сама себе - знак так же отбрасывается, как и раньше.

 

Зато потестил Кейл - как и предполагал, работает по аналогии с IAR - чихает на стандарты, делит со знаком и его дальнейшей обработкой. Наш человек :)

 

Подставлял в IAR вместо sizeof() переменную с типом size_t - без разницы, никакого превращения Int в беззнаковый тип не происходит, всё работает как и раньше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да. Было бы любопытно посмотреть на распечатку ассеблерного кода в том и другом случае.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да. Было бы любопытно посмотреть на распечатку ассеблерного кода в том и другом случае.

Вы про IAR? Уточните, пожалуйста.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы про IAR? Уточните, пожалуйста.

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

Честно говоря, я не думал про какой-то конкретный компилятор.

Я под Линем сижу, могу притащить сюда листин от gcc. (Если кто-нибудь меня не опередит к этому времени, гы-гы!)

 

Давайте какой-нибудь простенький код обуликуем, откомпилируем и сравним. Внимание нужно будет уделить именно арифметическим командам проца, которые как раз занимаются вычислением деления int на size_t.

 

Ну что, попробуем сделать?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Без проблем, только я сейчас на работе, и смогу добраться до компа только к ночи, и то не надолго.

Думаете, стоит расмотреть только деление, или пройтись по остальным операциям?

Хотя разницы не будет, вероятнее всего.

 

Постараюсь привести пример с делением и его код из под трех компиляторов - GCC, IAR и Keil. Последний под ARM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Коллеги , а давайте в отдельной теме. Эта всё таки про студию

Разделил.

Модератор

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Несколько устав уже от нюансов по поводу интерпретации стандатров различными компиляторами, нашёл всё таки время "добить" код, прогнав его через 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:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Чудеса оптимизации. Умеет определять, что после деления 0...65535 на 20 получится 0...3276, после преобразования к знаковому будет не отрицательным у ветка для t<0 не нужна.

Код IAR (v6.21):

...

Здесь уже ошибки нет, применяется деление со знаком.

Однако, если скомпилировать не Release код, а Debug, при тех же настройках оптимизации, получается код с беззнаковым делением.

Интересно :05:

Увы, IAR не вызывает доверия. Самый худший вариант, когда результат зависит от включения отладки :(.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...