получить правильный адрес символа * - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь понять поведение манипуляции char * в C. Вот мой код драйвера:

char *str1 = malloc(30);
char *str2 = "hello programmers.";
char *str4 = "and have a nice day.";
char *str5 = my_strcat(str2, str4);
my_strcpy(str1, str2);

и моя реализация для strcpy:

void my_strcpy(char *dest, char *src){
  while ((*dest++ = *src++)); //dest value is at end of char*
}

1.при выходе из my_strcpy, насколько я понимаю, dest должен указывать на конец строки (потому что мы продолжали увеличивать его).

Теперь давайте посмотрим на мою строку:

char* my_strcat(char *first, char *second){
  int l_first = strlen(first), l_second = strlen(second);
  char *tmp = malloc (l_first + l_second + 1);

  while ((*tmp++ = *first++));
  tmp--; // overwrite tmp's "\0"
  while ((*tmp++ = *second++)); // tmp value is end of char*
  tmp-=(l_first+l_second + 1); // rewinding pointer to string start.
  return tmp;
}

2.Мне пришлось вручную «перемотать» tmp, чтобы он правильно печатал вне функции.

Мой вопрос , короче говоря, почему я получаю такое поведение?Я не очень уверен, как описать мой вопрос, я надеюсь, что это было достаточно ясно.Почему мне пришлось «перематывать» мой указатель во второй функции, а не в первой?Более того, почему мне не пришлось «перематывать» src и dest в первой функции?

Возможные объяснения, о которых я подумал:

  1. char * было передано по значению функциям, и поэтому мне не пришлось перематывать src и dest - отладчик ошибочно проверил (проверенные адресавход и выход из области действия функции).
  2. в первой функции я передаю dest указатель, который был выделен вне области действия, тогда как во второй функции tmp было выделено внутри области.

Спасибо (я пытался предоставить столько информации и попыток найти решения, как хороший вопрос SO, извините, если он вышел слишком долго)

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

если вы хотите изменить указатель dest, вам нужно передать ссылку на него:

char* my_strcat(const char **dest, const char *source){
  size_t l_first = strlen(first), l_second = strlen(second);
  char *tmp = malloc (l_first + l_second + 1);
  char *result = temp;
  const char *tmpdest = *dest;

  if(tmp)
  {
      while ((*tmp++ = *tmpdest++));
      tmp--; // overwrite tmp's "\0"
      while ((*tmp++ = *second++)); // tmp value is end of char*
      *dest = result;
  }
  return result;
}
0 голосов
/ 18 сентября 2018

Почему мне пришлось «перематывать» мой указатель во второй функции, а не в первой?Более того, почему мне не пришлось «перематывать» src и dest в первой функции

Это потому, что в C все передается по значению.

  1. Когда мы передаем по значению, мы передаем копию переменной в функцию.

  2. Когда мы передаем по ссылке, мы передаем псевдонимпеременная для функции.Он копирует значение указателя, адреса в функцию.

Следовательно, когда вы делаете (*dest++ = *src++), вы не увеличиваете фактические переменные, поэтому ваши str2 и str4 остается неизменным.

В случае char* my_strcat(char *first, char *second) вы возвращаете локальный указатель, который указывает на последний символ в объединенной строке, поэтому вам нужно перемотать назад.

Если вы не хотитечтобы перемотать указатель, просто используйте один фиктивный указатель, указывающий на начало tmp и return фиктивный указатель, как показано ниже.

char* my_strcat(char *first, char *second){
  int l_first = strlen(first), l_second = strlen(second);
  char *tmp = malloc (l_first + l_second + 1);

  char *result = temp;

  while ((*tmp++ = *first++));
  tmp--; // overwrite tmp's "\0"
  while ((*tmp++ = *second++)); // tmp value is end of char*

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