Как функция printf () обрабатывает строки, возвращаемые функциями, используя глобальные буферы? - PullRequest
0 голосов
/ 08 ноября 2018

Я написал небольшой код, который печатает текущую дату в определенном формате.Чтобы вернуть все данные даты (день недели, день месяца, название месяца и т. Д.), Я использую функции типа const char *, которые передаютданные в виде строки для переменной, которая служит буфером, а затем передает буфер основной функции.

Следующий код представляет работу моей программы очень простым способом:

#include <stdio.h>
#include <string.h>

char
buff[16];

const char
*printStr1 (char *str1)
{
    strncpy(buff, str1, sizeof(str1));
    return buff;
};

const char
*printStr2 (char *str2)
{
    strncpy(buff, str2, sizeof(str2));
    return buff;
};


int
main()
{
    printf("%s%s", printStr1("foo"), printStr2("bar"));
    return 0;
}

Моя проблема заключается в следующем: при передаче всех данных в буфер и возврате их в основную функцию последние два данных совпадают (последние данные не печатаются, вместо этого выводится то, что уже было в буфере, то есть, вторые последние данные).

Это происходит только тогда, когда я использую одну функцию printf () , чтобы показать все данные, как в примере выше.Если я не использую буфер для возврата данных (я напрямую возвращаю аргумент, переданный функции) или использую printf () для всех данных, все выполняется правильно.

PS : я пытался решить эту проблему, используя такие функции, как memset () , чтобы очистить буфер, но он не работает, единственное, что я могу сделать, - это использовать отдельный буфер для каждой информации (для каждой функции).

Надеюсь, я хорошо выразил свою проблему.

Ответы [ 3 ]

0 голосов
/ 08 ноября 2018

Этот код:

printf("%s%s", printStr1("foo"), printStr2("bar"));

эквивалентно этому:

const char *p1 = printStr1("foo");
const char *p2 = printStr2("bar");
printf("%s%s", p1, p2);

или это (в зависимости от компилятора):

const char *p2 = printStr2("bar");
const char *p1 = printStr1("foo");
printf("%s%s", p1, p2);

Теперь должно быть понятно, почему вы получаете вывод, который получаете.

0 голосов
/ 08 ноября 2018

В дополнение к @ Жан-Франсуа Фабр хороший ответ, ...

Для печати printStr1("foo"), printStr2("bar") с 1 printf() необходимы отдельные буферы.

Начиная с C99, код может использовать составные литералы .

#include <stdio.h>
#include <string.h>

#define PRINT_N 16

const char *printStr1(char *dest,  size_t n, const char *str) {
  snprintf(dest, n, "%d %s\n", 1, str);
  return dest;
}

const char *printStr2(char *dest,  size_t n, const char *str) {
  snprintf(dest, n, "%d %s\n", 2, str);
  return dest;
}

// compound literals -------------v-----------------v
#define PRINT_STR1(src) printStr1((char [PRINT_N]){0}, PRINT_N, (src))
#define PRINT_STR2(src) printStr2((char [PRINT_N]){0}, PRINT_N, (src))

int main() {
  printf("%s%s\n", PRINT_STR1("foo"), PRINT_STR2("bar"));
  printf("%s%s%s%s\n", PRINT_STR1("foo"), PRINT_STR2("bar"), PRINT_STR2("foo"), PRINT_STR1("bar"));
}

выход

1 foo
2 bar

1 foo
2 bar
2 foo
1 bar
0 голосов
/ 08 ноября 2018

Помимо проблемы sizeof (которую вы пропускаете из-за небольших размеров строк), ваша проблема не связана с printf

Код сначала оценивает аргументы, а затем передает их printf. Последний оцененный аргумент «выигрывает», и printf получает один и тот же аргумент дважды.

Чтобы использовать только один локальный буфер, разделите ваш printf вызов:

printf("%s%s", printStr1("foo"), printStr2("bar"));

можно переписать на:

printf("%s", printStr1("foo"));
printf("%s", printStr2("bar"));

после печати значение может измениться, это не имеет значения:)

Поскольку в C нет сборщика мусора или строковых объектов, вы не можете просто выделить отдельные буферы и вернуть их для передачи в printf, иначе вы получите утечки памяти, поэтому в C нет интеллектуального и удобочитаемого решения для таких задач. вопросы.

Тем не менее, в одном C-проекте, который я сделал, я использовал вращающийся список строк (несколько буферов, сначала вход, затем выход). Сделайте 10 буферов, и вы можете использовать до 10 аргументов в одной и той же функции, и она будет работать правильно.

...