ПроблемаНеправильное употребление значения расширенного символа знака происходит, когда вы преобразуете со знаком или плоскость char
тип данных к более широкому целочисленному типу данных с расширением знака. Вы затем используете получившееся расширенное знаком значение в качестве индекса массива для сравнения с EOF или в качестве аргумента к обрабатывающей символ функции.
РискСравнение с EOF: Предположим, ваш компилятор реализует плоскость char
тип, как подписано. В этой реализации символ с десятичной формой 255 (–1 в дополнительной форме two) хранится как значение со знаком. Когда вы преобразуете char
переменная к более широкому типу данных int
например, знаковый бит сохраняется (расширение знака). Это расширение знака приводит к символу с десятичной формой 255 преобразовываемый в целое число –1, который нельзя отличить от EOF.
Использование в качестве индекса массива: подобным обоснованием вы не можете использовать расширенную знаком плоскость char
переменные как индекс массива. Если знаковый бит сохраняется, преобразование из char
к int
может привести к отрицательным целым числам. Необходимо использовать положительные целочисленные значения для индекса массива.
Аргумент к обрабатывающей символ функции: подобным обоснованием вы не можете использовать расширенную знаком плоскость char
переменные в качестве аргументов к обрабатывающим символ функциям объявляются в ctype.h
, например, isalpha()
или isdigit()
. Согласно стандарту C11 (Раздел 7.4), если вы предоставляете целочисленный аргумент, который не может быть представлен как unsigned char
или EOF, получившееся поведение не определено.
ФиксацияПеред преобразованием в более широкий целочисленный тип данных, бросок со знаком или плоскость char
оцените явным образом unsigned char
.
Пример - значение расширенного символа знака по сравнению с EOF#include <stdio.h>
#include <stdlib.h>
#define fatal_error() abort()
extern char parsed_token_buffer[20];
static int parser(char *buf)
{
int c = EOF;
if (buf && *buf) {
c = *buf++;
}
return c;
}
void func()
{
if (parser(parsed_token_buffer) == EOF) {
/* Handle error */
fatal_error();
}
}
В этом примере, функциональном parser
может пересечь вход buf
строки
. Если символ в строке имеет десятичную форму 255, когда преобразовано в int
переменная c
, его значение становится –1, который неотличим от EOF
. Более позднее сравнение с EOF
может привести к положительной лжи.
Коррекция — бросок к unsigned char
Перед преобразованиемОдна возможная коррекция должна бросить плоскость char
значение к unsigned char
перед преобразованием в более широкий int
ввод.
#include <stdio.h>
#include <stdlib.h>
#define fatal_error() abort()
extern char parsed_token_buffer[20];
static int parser(char *buf)
{
int c = EOF;
if (buf && *buf) {
c = (unsigned char)*buf++;
}
return c;
}
void func()
{
if (parser(parsed_token_buffer) == EOF) {
/* Handle error */
fatal_error();
}
}