printf модифицирует строку - PullRequest
1 голос
/ 04 декабря 2009

Используя printf для печати "\4unix\5lancs\2ac\2uk\0" вместо печати в виде ♦unix♣lancs☻ac☻uk я получаю мусор (♫ ,►E¦§Qh ↕).

Я не могу найти объяснения этому; Я использую следующий метод для токенизации строки:

/**
 * Encode the passed string into a string as defined in the RFC.
 */
char * encodeString(char *string) {
    char stringCopy[128];
    char encodedString[128] = "";
    char *token;

    /* We copy the passed string as strtok mutates its argument. */
    strcpy(stringCopy, string);

    /* We tokenise the string on periods. */
    token = strtok(stringCopy, ".");

    while (token != NULL) {
        char encodedToken[128] = "";

        /* Encode the token. */
        encodedToken[0] = (char) strlen(token);
        strcat(encodedToken, token);

        /* Add the encodedString token to the encodedString string. */
        strcat(encodedString, encodedToken);

        /* Prepare for the next iteration. */
        token = strtok(NULL, ".");
    }

    /* A null character is appended already to the encoded string. */

    return encodedString;
}

И следующий код в моем драйвере для печати результата при токенизации "unix.lancs.ac.uk":

int main(int argc, char *argv[]) {
    char *foo = "unix.lancs.ac.uk";
    char *bar = encodeString(foo);

    printf("%s\n", bar);

    return 0;
}

Если я добавлю printf для печати encodedString в конце метода encodeString, я не получу распечатанный мусор (скорее, ♦unix♣lancs☻ac☻uk дважды).

(При отладке я замечаю, что фактическое содержимое памяти изменяется.)

Может кто-нибудь объяснить мне это явление?

Ответы [ 3 ]

8 голосов
/ 04 декабря 2009

Вы возвращаете указатель на массив encodedString, который является локальным для функции encodeString() и имеет автоматическую продолжительность хранения.

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

Вы можете исправить это, задав encodedString статическую длительность хранения:

static char encodedString[128];

encodedString[0] = '\0';

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

4 голосов
/ 04 декабря 2009

Когда вы говорите:

 return encodedString;

вы возвращаете локальную переменную, которая перестанет существовать к тому времени, как вы ее используете Быстрый взлом состоит в том, чтобы сделать encodedString статическим.

3 голосов
/ 04 декабря 2009

НЕ использовать функции, возвращающие строки.

Отправьте адрес строки как paremeter и измените его в функции.

Компилятор должен отображать предупреждение. Не игнорируйте предупреждения компилятора, особенно в C.

Ваша функция должна быть такой:

void encodeString(char *string, char *encodedString)
{
.
.
.
}

См. здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...