Ошибка компиляции C для основной функции

Я пытаюсь написать свою собственную версию strcat (я называю это "append"). Вот что у меня есть:

#include <stdio.h>

int main() {

  char *start = "start";
  char *add = "add";
  append(start, add);
  printf(start);

}

void append(char *start, char *add) {
  //get to end of start word
  char *temp = &start;
  while (*temp != '\0') {
    temp++;
  }
  *temp = *add;
  while (*temp != '\0') {
     *temp = *add; 
  }
}

Когда я компилирую, я получаю 3 предупреждения и ошибку:

1) предупреждение: неявное объявление функции 'append' недопустимо в C99

2) предупреждение: строка формата не является строковым литералом (потенциально небезопасно)

3) ошибка: конфликтующие типы для 'добавления'

Я не вижу, как аргументы, которые я передаю в мою функцию добавления, находятся в главном конфликте с определением функции ниже.

4) предупреждение: несовместимые типы указателей, инициализирующие 'char *' выражением типа 'char **'; Удалить &

Почему я хочу удалить & Вот? Я думал, что мог бы объявить и инициализировать мой char указатель на правильный адрес памяти все сразу.

Буду признателен за любую оказанную помощь.

4 ответа

Решение

У вас есть несколько проблем с этим коротким кодом. Сначала у вас есть

предупреждение: неявное объявление функции 'append' недопустимо в C99

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

Продолжая со следующим предупреждением:

предупреждение: строка формата не является строковым литералом (потенциально небезопасным)

Это потому, что вы предоставляете строковую переменную для printfЭто, как говорит предупреждение, небезопасно. Подумайте, например, о случае, когда вы читаете ввод от пользователя, и используете этот ввод в качестве строки формата для printf, Что помешает пользователю добавить коды формата во входную строку? А так как вы не передаете аргументы, откуда бы взялись аргументы для этих форматов?

А теперь ошибка:

ошибка: конфликтующие типы для 'добавления'

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


Теперь перейдем к другой серьезной проблеме, которая не отображается в виде ошибок или предупреждений компилятора, а именно к неопределенному поведению.

Проблема в том, что ваш start а также add переменные указывают на строковые литералы. Строковый литерал предназначен только для чтения (на самом деле строковый литерал является указателем на массив неизменяемых символов). Первая проблема заключается в том, что вы пытаетесь изменить содержимое этих массивов, вторая - это то, что массивы имеют настолько большой размер, насколько необходимо, и вы пишете вне этой памяти. Обе эти проблемы являются причинами неопределенного поведения.

1) предупреждение: неявное объявление функции 'append' недопустимо в C99

а также

3) ошибка: конфликтующие типы для 'добавления'

потому что вы не предоставили прототип append() перед его использованием. Вам необходимо добавить предварительное объявление функции перед ее использованием. добавлять

void append(char *start, char *add);

до main() или поместите определение функции перед main()

Далее, в случае

 char *start = "start";
 char *add = "add";

start а также add являются указателями на строковые литералы. Они обычно помещаются в постоянную память, что означает, что вы не можете изменить содержимое. Любая попытка сделать это приведет к неопределенному поведению.

Тогда относительно

2) предупреждение: строка формата не является строковым литералом (потенциально небезопасно)

printf(start);

неправильное использование в этом случае. Вы должны использовать его как

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

Проверьте справочную страницу printf() Больше подробностей.

и наконец,

4) предупреждение: несовместимые типы указателей, инициализирующие 'char *' выражением типа 'char **'; Удалить &

из-за

char *temp = &start;

вам нужно использовать что-то вроде

char *temp = start;   //start is a char *, no need for & here

Примечание: рекомендуемая подпись main() является int main(void),

Но это самая простая часть, которую может обнаружить компилятор.

Хуже всего то, что, как вы заявили start как char *start = "start", он указывает только на массив из 6 символов (5 букв + завершающий ноль).

Поэтому, когда вы пытаетесь добавить add в конце вы получаете неопределенное поведение (для записи вне массива)! В этом случае вы пишете в память, где что-либо еще может быть => ваша программа может сломаться или segfault.

C99 довольно ограничен в том, как он хочет, чтобы вы объявляли вещи.

Как сказал Сурав, 1 и 3 вызваны вашим append() Функция используется до того, как она объявлена ​​в файле, что заставляет компилятор генерировать неявное объявление для вас. Переместить append() функция выше main() чтобы исправить это (или добавить прототип функции).

4 вызывается этой строкой: char *temp = &start;

temp здесь на самом деле char**, так как вы берете адрес char*

Другие вопросы по тегам