скопировать строку в c - вопрос памяти: - PullRequest
1 голос
/ 14 августа 2010

рассмотрим следующий код:

t[7] = "Hellow\0";
s[3] = "Dad";
//now copy t to s using the following strcpy function:

void strcpy(char *s, char *t) {
    int i = 0;

    while ((s[i] = t[i]) != '\0')
        i++;
}

указанный выше код взят из "Книги по языку программирования C".мой вопрос - мы копируем 7 байтов в то, что было объявлено как 3 байта.откуда мне знать, что после копирования другие данные, которые были после s [] в памяти, не были удалены?

и еще один вопрос: char *s идентичен char* s?

Спасибо!

Ответы [ 5 ]

2 голосов
/ 14 августа 2010

Как вы правильно заметили, передача s[3] в качестве первого аргумента приведет к перезаписи некоторой памяти, которая вполне может быть использована другим.В лучшем случае ваша программа сразу же рухнет;в худшем случае он будет продолжать работать, повреждаться и в конечном итоге повредить что-то, с чем он должен был справиться.

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

Кстати, похоже, вы поменялись местами s и t;Вероятно, это означало следующее:

void strcpy(char *t, char *s) {
    int i = 0;

    while ((t[i] = s[i]) != '\0')
        i++;
}

Теперь вы можете скопировать s[4] в t[7], используя эту измененную подпрограмму strcpy:

char t[] = "Hellow";
char s[] = "Dad";

strcpy(t, s);

(редактировать: длинаs теперь исправлено)

2 голосов
/ 14 августа 2010

О первом вопросе.

Если вам повезет, ваша программа потерпит крах.

Если вы этого не сделаете, он продолжит работу и перезапишет области памяти, которые не должны быть затронуты (поскольку вы не знаете, что на самом деле там). Это было бы адом для отладки ...

О втором вопросе.

И char* s, и char *s делают одно и то же. Это просто вопрос стиля.

То есть char* s можно интерпретировать как "s имеет тип char указатель", а char *s можно интерпретировать как "s - указатель на char" Но на самом деле, синтаксически это то же самое.

1 голос
/ 14 августа 2010

Я буду считать, что и s, и t (выше определения функции) являются массивами char.

откуда мне знать, что после копирования другие данные, которые были после s [] в памяти, не были удалены?

Нет, это хуже, вы вызываете неопределенное поведение, и мы знаем это, потому что так говорится в стандарте. Все, что вам разрешено делать после трех элементов в s, это сравнение. Назначение строго нет-нет. Продвигайтесь дальше, и вам даже не разрешено сравнивать.

и еще один вопрос: char s идентичен char s?

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

1 голос
/ 14 августа 2010

Этот пример ничего не делает, вы еще не вызываете strcpy. Но если вы сделали это:

strcpy(s,t);

Это было бы неправильно по нескольким причинам:

  • Строка s не заканчивается нулем. В C единственный способ, которым strcpy может узнать, где заканчивается строка, - найти '\ 0'. Функция может думать, что s бесконечно, и это может повредить вашу память и вызвать сбой программы.
  • Даже если нулевое значение завершено, как вы сказали, размер s равен только 3. По той же причине strcpy будет записывать память за пределы, где заканчивается s , что может быть катастрофическим результаты.

Обходной путь для этого в C - функция strncpy (dst, src, max), в которой вы указываете максимальное количество символов для копирования. Тем не менее помните, что эта функция может генерировать ненулевую завершающую строку, если src короче max char.

0 голосов
/ 14 августа 2010

строковый литерал "Hellow\0" равен "Hellow"

, если вы определите

t[7] = "Hellow";
s[7] = "Dad";

, ваш пример определен и вылетает не.

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