2013-06-28 4 views
2

версия 1указатели и строки в C, различные вопросы

char *cad1="hell"; 
    char *cad2="home"; 
    int j; 
    cad2=cad1; 
    for (j=0;j<4;j++){ 
     printf("%c",cad1[j]); 
    } 
    cad2[0]='a'; 
    for (j=0;j<4;j++){ 
     printf("%c",cad2[j]); 
    } 

версия 2

char cad1[]="hell"; 
    char cad2[]="home"; 
    int j; 
    cad2=cad1; 
    for (j=0;j<4;j++){ 
     printf("%c",cad1[j]); 
    } 
    cad2[0]='a'; 
    for (j=0;j<4;j++){ 
     printf("%c",cad2[j]); 
    } 

версия 3

char cad1[]="hell"; 
    char *cad2="home"; 
    int j; 
    cad2=cad1; 
    for (j=0;j<4;j++){ 
     printf("%c",cad1[j]); 
    } 
    cad2[0]='a'; 
    for (j=0;j<4;j++){ 
     printf("%c",cad2[j]); 
    } 

Вопрос, который у меня есть, поэтому версия 1 вешает Dev C++ ?, версия 2 говорит, что существует несовместимое назначение в cad2 = cad1? и почему версия 3 работает нормально?

+2

Возможный дубликат [C-FAQ: массивы и указатели] (http://c-faq.com/aryptr/index.html) и http://c-faq.com/decl/strlitinit.html – Elazar

+1

1) 'предупреждение: инициализация исключает 'const' классификатор из целевого типа указателя' 2)' несовместимые типы при назначении типа 'char [5]' из типа 'char *' ' –

+0

возможный дубликат [Почему я получаю ошибку сегментации, когда запись в строку?] (http://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-string) – Lundin

ответ

0

В версии 1 cad2 равен cad1, который указывает на постоянную строку "hell". Позже вы пытаетесь изменить эту константную строку, что непредсказуемо. Версия 3, напротив, имеет cad1, объявленный как массив char, поэтому вы получаете непостоянную копию строки, поэтому ее изменение будет работать.

Для версии 2 это, вероятно, потому, что оба являются массивами (не указателями), поэтому я уверен, что там есть некоторые проблемы.

6

При объявлении указателя, как,

char *cad1="hell"; 

"hell" называется постоянная строка буквального и поэтому могут храниться в памяти только для чтения. - компилятор имеет право выбирать все, что ему нравится.

Но когда вы объявляете его как,

char cad2[]="hell"; 

"hell" хранится в качестве элемента массива. то есть, он будет храниться в виде,

cad[0] = 'h', cad[1] = 'e', cad[2] = 'l', cad[3] = 'l', cad[4] = '\0' 

C не гарантирует определенное поведение для изменения constant literals. Это может привести к сбою зависания или испортить другие достоверные данные. Его называют неопределенным поведением.

Поскольку вы меняете cad1, который указывает на constant literal, ваше приложение висит.


В версии 2, как cad1 и cad2 имеют тип массива. Прямые назначения массива в C являются незаконными. Таким образом, вы получили ошибку. Обратитесь к this link за все подробности, как упоминалось другими.


Чтобы ответить, почему версия 3 работает,

cad1 является массивом и cad2 является указателем здесь. В заявлении cad2 = cad1 вы сделали cad2, чтобы указать память, которая может быть изменена (при этом размер ограничен). Таким образом, изменение cad1 и cad2 такое же, как они указывают на одну и ту же модифицируемую память.

+3

FYI это называется «неопределенным поведением» ». –

+0

@VoidPointer, но почему case 3 позволяет передать член массива указателю, который хранится в памяти только для чтения? – Layla

+0

@ Manuel проверить обновленный ответ и ссылку .. – VoidPointer

0

Если cad объявлен как char* cad="hell"; то это строка символов (длина 4 плюс 1 для нулевого терминатора) и любой попытка модифицировать строку буквальной является неопределенного поведения. Может произойти все, что угодно.

char cad[]="home"; выделит 5 char s на стек, cad [4] - '\ 0' - нулевой ограничитель; используемый многими строковыми функциями в C при моделировании набора char s в виде строки для обозначения конца строки. Вы можете изменять эти данные, хотя изменение cad[4] вызовет у вас проблемы при использовании функций библиотеки строк C, поскольку вы удалите их условие остановки.

В вашем коде есть cad2=cad1; Обратите внимание, что это не копирует строку, просто указатель; используйте strcpy в стандартной библиотеке C для копирования строк.

Действительно, вы должны написать const char* cad="hell";. Более новые компиляторы C++ будут настаивать на этом.

0
  • Почему версия 1 висит dev C++?

Читать комментарии:

char *cad1="hell"; // pointer to constant string "hell" 
char *cad2="home"; 
cad2=cad1;   // now cad2 points to constant string "hell" too 
cad2[0]='a';  // modifying of constant string causes undefined behaviour. 
  • версия 2 говорит, что есть несовместимое назначение в cad2 = cad1?

Читать комментарии:

char cad2[]="home"; // cad2 is array 
cad2=cad1;   // error because you can not assign to arrays in C. 
  • почему версия 3 работает нормально?

Читать комментарии:

char cad1[]="hell"; // cad1 is array 
char *cad2="home"; 
cad2=cad1;   // now cad2 point to first element of array cad1 
cad2[0]='a';   // you can modify arrays in C 

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