спецификатор формата для короткого целого - PullRequest
0 голосов
/ 01 июня 2010

Я неправильно использую спецификаторы формата в C. Несколько строк кода:

int main()
{
        char dest[]="stack";
        unsigned short val = 500;
        char c = 'a';

        char* final = (char*) malloc(strlen(dest) + 6);

        snprintf(final, strlen(dest)+6, "%c%c%hd%c%c%s", c, c, val, c, c, dest); 

        printf("%s\n", final);
        return 0;
}

Я хочу скопировать на

final [0] = случайный символ final [1] = случайный символ final [2] и final [3] = короткий массив final [4] = еще один символ ....

Моя проблема в том, что я хочу скопировать два байта короткого int в 2 байта окончательного массива.

спасибо.

Ответы [ 8 ]

5 голосов
/ 01 июня 2010

Я запутался - проблема в том, что вы говорите strlen(dest)+6, который ограничивает длину строки final до 10 символов (плюс нулевой терминатор). Если вы скажете strlen(dest)+8, то для полной строки будет достаточно места.

Обновление

Несмотря на то, что short может иметь размер всего 2 байта, при печати в виде строки каждый символ будет занимать байт. Это означает, что для записи короткого замыкания в строку может потребоваться до 5 байт, если вы пишете число выше 10000.

Теперь, если вы записали короткое в строку в виде шестнадцатеричного числа, используя спецификатор формата %x, это займет не более 2 байтов.

1 голос
/ 01 июня 2010

Простой ответ: вам выделено достаточно места только для strlen (dest) + 6 символов, когда в реальности все выглядит так, как будто у вас будет 8 дополнительных символов ... так как в вашем номере 2 символа + 3 символа + 2 символа после + dest (5 символов) = 13 символов при выделении 11 символов.

1 голос
/ 01 июня 2010

При форматировании число (500) занимает три пробела, а не один. Таким образом, ваша snsprintf должна указывать окончательную длину как strlen(dest)+5+3. Затем также исправьте ваш malloc вызов для настройки. Если вы хотите вычислить strlen числа, сделайте это с помощью вызова, подобного этому strlen(itoa(val)). Кроме того, я не могу забыть NULL в конце dest, но я думаю, что strlen принимает это во внимание, но я не уверен.

1 голос
/ 01 июня 2010

Unsigned short с может занять до 5 символов, верно? (0 - 65535)

Похоже, вам нужно выделить 5 символов для unsigned short, чтобы охватить все значения.

Что будет указывать на использование этого:

char* final = (char*) malloc(strlen(dest) + 10);
1 голос
/ 01 июня 2010

Вы теряете один байт, потому что думаете, что переменная short занимает 2 байта. Но это занимает три: по одному на каждый символ цифры («5», «0», «0»). Также вам нужен '\0' терминатор (+1 байт).

==> Вам нужно strlen(dest) + 8

1 голос
/ 01 июня 2010

Вам нужно выделить место для 13 символов, а не для 11. Не забудьте завершающий NULL.

0 голосов
/ 02 июня 2010

Похоже, что основное недоразумение заключается в том, что «2-байтовый» шорт не может быть представлен на экране как 2 1-байтовых символа.

Сначала оставьте достаточно места:

char* final = (char*) malloc(strlen(dest) + 9);

Весь диапазон возможных значений для 1-байтового символа не печатается. Если вы хотите отобразить это на экране и быть читабельным, вам придется закодировать 2-байтовую короткую строку в 4 шестнадцатеричных байта, например:

## as hex, 4 characters
snprintf(final, sizeof(final), "%c%c%4x%c%c%s", c, c, val, c, c, dest);

Если вы пишете это в файл, это нормально, и вы можете попробовать следующее:

## print raw bytes, upper byte, then lower byte.
snprintf(final, sizeof(final), "%c%c%c%c%c%c%s", c, c, ((val<<8)&0xFF), ((val>>8)&0xFF), c, c, dest); 

Но это не имеет смысла для человека, смотрящего на него, и он чувствителен к порядку байтов. Я настоятельно рекомендую против этого.

0 голосов
/ 01 июня 2010

Используйте 8 вместо 6 на:

char* final = (char*) malloc(strlen(dest) + 6);

и

snprintf(final, strlen(dest)+6, "%c%c%hd%c%c%s", c, c, val, c, c, dest);
...