Почему strcpy () работает без включения - PullRequest
0 голосов
/ 02 апреля 2019

Я работаю с примером C и использую функцию strcpy(), но забыл включить <string.h>, хотя я включил <stdio.h>.К моему удивлению код успешно прошел.Ниже приведен код, который я выполняю:

#include <stdio.h>

int main() {
   char message[10];
   int count, i;

   strcpy(message, "Hello, world!");

   printf("Repeat how many times? ");
   scanf("%d", &count);

   for(i=0; i < count; i++) {
      printf("%3d - %s\n", i, message);
   }
}

Я использую gcc version 3.3.6 (Ubuntu 1:3.3.6 - 15ubuntu1)

Я даже не получил никаких предупреждений компиляции.

enter image description here

Почему мой код работает без включения <string.h>?

Заранее спасибо.

Ответы [ 4 ]

3 голосов
/ 02 апреля 2019

Насколько я помню, GCC 3 по умолчанию соответствовал C89 плюс расширения GNU.C89 позволял вызывать функции без предварительного объявления - предполагалось, что они возвращают int, а их типы параметров выводятся из типов аргументов.Если получающийся в результате неявный тип совпадал с фактическим типом вызываемой функции (что более вероятно в устаревшем коде C, чем в современном коде), то все было хорошо.Если нет, то поведение было неопределенным, но с неопределенным поведением может случиться что угодно, даже то, что ожидал программист, написавший код.

Кроме того, хотя в стандартах не указано, что какой-либо из стандартных заголовковвключают другие заголовки, им не запрещено делать это, и на практике в некоторых реализациях C некоторые из них делают.Если случится так, что stdio.h вашей реализации включает в себя string.h или иным образом предоставит совместимое определение для strcpy(), то это просто отлично подойдет с этой реализацией .Однако, если вы на это полагаетесь, намеренно или нет, то вы рискуете неожиданного сбоя при попытке использовать вашу программу с другой реализацией.

Наконец, обратите внимание, что GCC 3.3 очень старый.Если это вообще возможно, вы должны перейти на что-то более новое.Даже в стабильной, долговременной стабильности Linux, как правило, используют по крайней мере версии поздних версий серии 4.x, а последняя версия - GCC 8.3.

3 голосов
/ 02 апреля 2019

Компилятор принимает int strcpy() и вызывает древнее поведение обратной совместимости.Аргументы указателя являются одним из типов, для которых это работает, поэтому все в порядке.

Не зависит от этого.Рельсы безопасности выключены.

2 голосов
/ 02 апреля 2019

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

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

Компилятор берет то, что вы написали, поэтому адреса message и Hello, world! и предполагает, что функция возвращает int. Вы рискуете, не сообщая компилятору, как он должен компилировать код благодаря include. Результатом является неопределенное поведение.

Кстати, Hello, world! занимает 14 символов, 13 + завершающий \0, что на 4 больше, чем в вашем объявлении message. Это неопределенное поведение, так как дополнительные 4 символа будут записаны там, где они не должны. Кажется, работает, сбой ...

Вы не можете полагаться на программу, показывающую ожидаемый результат. Это неопределенное поведение.

Всегда компилируйте с параметрами предупреждений, такими как -Wall, и рассмотрите возможность исправления всех предупреждений.

0 голосов
/ 02 апреля 2019

Компилятор знает некоторые «встроенные» функции (printf() - еще один пример для некоторых компиляторов) и компенсирует вашу ошибку, предоставляя ее.Это плохая привычка полагаться на это, потому что даже если ваш сегодняшний компилятор сделает это, ничто не гарантирует, что другой сделает то же самое, поэтому скомпилированный код не будет предсказуемым.

Попробуйте компилировать с -Wall -Wextra чтобы компилятор отображал больше предупреждений, включая предупреждения для забытого заголовка: gcc -o input input.c -Wall -Wextra.

Также смотрите здесь: предупреждение: несовместимое неявное объявление встроенной функции 'xyz'

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