2015-06-22 1 views
3
#include <stdio.h> 
int main() 
{ 
    unsigned char y; 
    scanf("%hhu", &y); 
    printf("%hhu", y); 
    return 0; 
} 

Этого код работа в порядке с г ++ (Dev C++), но причины повреждения стека в Visual Studio (2010), это VS ошибки или есть какой-либо другой способ ввода unsigned char в VS с использованием scanf();?Стьки вокруг переменного было поврежден, после inputing неподписанного символа на зсапе

+4

Почему бы не использовать 'cin' и сохранить себе тип небезопасной головной боли? – PaulMcKenzie

+1

Просто выберите один язык: C ** или ** C++! Это разные языки. – Olaf

+0

Возможный дубликат [Почему scanf ("% hhu", char \ *) перезаписывает другие переменные, когда они являются локальными?] (Http://stackoverflow.com/questions/15825254/why-is-scanfhhu-char-overwriting- other-variables-when-they-are-local) – anatolyg

ответ

5

Похоже VS не обрабатывает %hhu: https://stackoverflow.com/a/15825386/1715829

Важная деталь в том, что вы используете Windows, и, предположительно, устаревшие или не соответствующие требованиям среды C (компилятор и стандартная библиотека). MSVCRT поддерживает только C89 (и даже тогда, не совсем правильно); в частности, в C89 не было модификатора «hh», и, вероятно, он интерпретировал «hh» так же, как «h» (т. е. короткий).

+0

'Похоже, что VS не обрабатывает% hhu правильно' Больше похоже на« вообще не обрабатывает », а не« не правильно ». Обработка «неправильно» подразумевает, что он * обрабатывается, но имеет ошибки. – PaulMcKenzie

+0

@PaulMcKenzie: Я достаточно уверен, я обновил свой ответ. – Buddy

+0

Связанный вопрос и ответ показывают, что MSVS рассматривает '% hhu' как'% u', то есть обрабатывает его неправильно. Вы можете сказать, что он вообще не обрабатывает 'hh'. – anatolyg

1

Просто, чтобы добавить немного больше деталей ...

коррупция происходит вокруг линии 1111 в input.c.

if (integer64) 
    *(__int64 UNALIGNED *)pointer = (unsigned __int64)num64; 
else 
if (longone) 
    *(long UNALIGNED *)pointer = (unsigned long)number; 
else 
    *(short UNALIGNED *)pointer = (unsigned short)number; 

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

При разборе строки формата счетчик longone изначально имеет значение 1 и уменьшается каждый раз, когда встречается символ «h». Позже (в приведенном выше фрагменте) longone используется в качестве флага, чтобы определить, является ли разобранное целое число 32 бита или нет.

Это поведение нормально, если используется "%hu", так как longone будет 0, и поэтому разобранное значение будет считаться 16 битами. Если, однако, используется "%hhu", longone будет равным -1, и поэтому разобранное значение будет считаться 32 битами.

В любом случае (32 или 16-битное значение) ваш указатель на указатель будет иметь больше, чем ожидаемый 1 байт, что приведет к повреждению стека.

Это поведение влияет на все связанные функции scanf(), поскольку Visual Studio реализует такие вещи, как swscanf_s(), делая входную строку похожим на дескриптор файла. Таким образом, все заканчивается функцией _tinput_s_l() (строка 368 в input.c), где проявляется вышеуказанная проблема.

MSDN documentation for Visual Studio 2010 префикс %h, но не префикс %hh.

What's new for Visual C++ in Visual Studio 2015 утверждает, что:

C99 конформности Visual Studio 2015 полностью реализует C99 Standard библиотеки, за исключением каких-либо функций библиотеки, которые зависят от компилятора функций, которые пока не поддерживаются Visual C++ компилятор (для пример, <tgmath.h> не реализован).

Который я читаю как «мы реализовали все, кроме бит, которого у нас нет, о чем мы не будем говорить».

Смежные вопросы