2016-01-26 4 views
-2

Я применил свои собственные strcpys, чтобы найти, существует ли какая-либо разница между src как const char * & char *, но не обнаружите разницы между следующими 2 & оба работали одинаково.Почему strcpy принимает const char * для src вместо char *?

char * my_strcpy(char*dest, char* src) 
{ 
    while ('\0' != *src) 
     *dest++ = *src++; 
    *dest++ = '\0'; 
     return dest; 
} 

char * my_strcpy2(char*dest, const char* src) 
{ 
    while ('\0' != *src) 
     *dest++ = *src++; 
    *dest++ = '\0'; 
    return dest; 
} 

Есть ли причина, по которой strcpy принимает указатель источника как const char * вместо char *?

+1

Это не так. 'strcpy' принимает' const char * src'. –

+0

ИМХО по историческим причинам. В большинстве случаев strcpy() может быть встроен, поэтому разница будет бесполезной в любом случае. – joop

+6

Фактически ['strcpy'] (http://en.cppreference.com/w/c/string/byte/strcpy) имеет свой исходный аргумент, определенный как' const char * restrict' со стандартного C99. См. [эта ссылка] (http://en.cppreference.com/w/c/language/restrict) для получения дополнительной информации о ключе 'ограничение'. –

ответ

6

Есть ли причина, по которой strcpy принимает указатель источника как char * вместо const char *?

Исходный указатель должен быть const char *. Причина распространена для всех функций (а не только strcpy), которые не намерены случайно изменять источник внутри функции.

Практика распространяется на обе библиотечные функции, такие как strcpy или ваши собственные пользовательские функции. Как и в случае с библиотечной функцией, например strcpy, нет никаких шансов, что источник случайно изменен. Но для вашей собственной (или любой другой) пользовательской функции все может случиться. И если вы измените его случайно, тогда вы получите ошибку компиляции, сообщающую вам об этом. И вот когда const имеет значение.

3

«не находите разницы между следующими 2» - какими могут быть различия в ваших самых смелых мечтах?

Единственное отличие, которое имеет объявление const, - со стороны абонента. По объявлению параметра const функция обещает не изменять память, доступную через указатель. Он обещает только прочитать его, что согласуется с семантикой strcpy(). (Примечание:.. Если функция фактически не запишет через указатель не гарантируется на всех Но он обещает)

Абонент может поэтому вызов функции с указателем на постоянных данных и предположим, что функция не будет попытайтесь написать ему.

Это важно синтаксический, логически и материально:

  • язык позволяет абоненту обеспечить указатель на константные данные в качестве аргумента (это не позволило бы, что для первой неконстантной версии).
  • Вызывающий может быть уверен, что чувствительные данные не будут изменены внутри функции в качестве побочного эффекта; Представьте себе указатель на структуры данных ядра здесь. (Counter-example: strtok() записывает в исходную строку, которая поэтому не объявлена ​​const!)
  • Данные могут быть физически доступны для чтения (например, могут быть записаны в ПЗУ контроллера), так что попытка написать ему бы вызвать, ну процитировать отличный Макс Барри: а "catastrophic system failure. (...) I'm not saying it's a big deal."
+0

* на самом деле не пишет через указатель, не гарантируется вообще * ... Правда, но если программист не делает зла ​​(бросает, чтобы удалить константу), компилятор будет жаловаться. –

+0

@ Jean-BaptisteYunès Это правда, что реализация должна использовать литье или сделать что-то еще более пугливое. –

0

для начала функционировать strcpy возвращает указатель на строку назначения. Ваша функция также должна возвращать указатель на строку назначения. Это общее соглашение для функций, которые обрабатывают строки в стандарте C.

Так функция может выглядеть следующим образом

char * my_strcpy(char *dest, const char *src) 
{ 
    char *p = dest; 

    while (*p++ = *src++); 

    return dest; 
} 

В этом случае можно назвать, например, следующим образом

const char *hello = "Hello, World!"; 
char s[14]; 

puts(s, hello); 

Заданием второго параметра функции как указатель на объекте константная символьная строка означает 1), что функция гарантирует, что она не изменит заостренную строку и 2) позволяет перейти к строкам постоянной константы.

Указатель на непостоянный объект может быть неявно преобразован в указатель на постоянный объект. Обратная операция не допускается без явного литья.

Таким образом, если параметр объявлен как указатель на константную строку, вы можете передать непостоянные строки вместе с константными строками в ту же функцию, что и аргументы. В противном случае функция не может вызываться с постоянными строками, потому что компилятор выдаст ошибку, заявив, что не может преобразовать объект типа const char * в объект типа char *.

+0

@BLUEPIXY Спасибо. Это была опечатка в результате копирования и вставки. –