Ошибка компиляции 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*