При выполнении вычитания указателей и первого указателя меньше второго, я получаю ошибку underflow с процессором ARM.Вычитание указателя, 32-битное ARM, отрицательное расстояние, сообщенное как postive
Пример кода:
#include <stdint.h>
#include <stdbool.h>
uint8_t * p_formatted_data_end;
uint8_t formatted_text_buffer[10240];
static _Bool
Flush_Buffer_No_Checksum(void)
{
_Bool system_failure_occurred = false;
p_formatted_data_end = 0; // For demonstration puposes.
const signed int length =
p_formatted_data_end - &formatted_text_buffer[0];
if (length < 0)
{
system_failure_occurred = true;
}
//...
return true;
}
Код сборки генерируется компилятором IAR является:
807 static _Bool
808 Flush_Buffer_No_Checksum(void)
809 {
\ Flush_Buffer_No_Checksum:
\ 00000000 0xE92D4070 PUSH {R4-R6,LR}
\ 00000004 0xE24DD008 SUB SP,SP,#+8
810 _Bool system_failure_occurred = false;
\ 00000008 0xE3A04000 MOV R4,#+0
811 p_formatted_data_end = 0; // For demonstration purposes.
\ 0000000C 0xE3A00000 MOV R0,#+0
\ 00000010 0x........ LDR R1,??DataTable3_7
\ 00000014 0xE5810000 STR R0,[R1, #+0]
812 const signed int length =
813 p_formatted_data_end - &formatted_text_buffer[0];
\ 00000018 0x........ LDR R0,??DataTable3_7
\ 0000001C 0xE5900000 LDR R0,[R0, #+0]
\ 00000020 0x........ LDR R1,??DataTable7_7
\ 00000024 0xE0505001 SUBS R5,R0,R1
814 if (length < 0)
\ 00000028 0xE3550000 CMP R5,#+0
\ 0000002C 0x5A000009 BPL ??Flush_Buffer_No_Checksum_0
815 {
816 system_failure_occurred = true;
\ 00000030 0xE3A00001 MOV R0,#+1
\ 00000034 0xE1B04000 MOVS R4,R0
Инструкция вычитания SUBS R5,R0,R1
эквивалентно:
R5 = R0 - R1
N
бит регистр CPSR
будет t, если результат отрицательный. Ссылка: Раздел A4.1.106 SUB из ARM Architecture Reference Manual
Пусть:
R0 == 0x00000000
R1 == 0x802AC6A5
Регистрация R5
будет иметь значение 0x7FD5395C
. N
бит регистра CPSR
: 0, с указанием результата не является отрицательным.
Приложение «Калькулятор Windows 7» сообщает об отрицательном значении, но только в том случае, если оно выражается как 64-разрядные: FFFFFFFF7FD5395C
.
В качестве эксперимента я использовал тип ptrdiff_t
для длины, и был сгенерирован тот же язык ассемблера.
Вопросы:
- Является ли это действительным поведение, чтобы получить результат вычитания указателя на опустошения?
- Каков рекомендуемый тип данных для просмотра расстояния как отрицательный?
Платформа:
Target Процессор: ARM Cortex A8 (TI AM3358)
Компилятор: IAR 7,40
Развитие платформы: Windows 7.
'p_formatted_data_end = 0; ', очевидно, не указывает на любом месте в пределах массива' formatted_text_buffer' (или байт после). Арифметика указателя на несвязанные объекты - это неопределенное поведение *. Обратите внимание, что бит знака в регистре флагов процессора отражает бит ms регистра или операции независимо от того, считаете ли вы значение без знака или подписью. –
Но не является ли вообще отрицательным результатом? Если вы вычтите указатель на 'formatted_text_buffer [3]' из указателя на 'formatted_text_buffer [0]' (8-битный массив), то итоговый '-3' сообщает вам, сколько элементов они находятся отдельно. –
Арифметика между двумя указателями, не указывающими на один и тот же массив, - UB. – Fredrik