2016-11-23 5 views
2

Я хотел бы скопировать source строку в номер dest. Если я скомпилирую следующую программу:Memset and characters

#include <stdio.h> 

int main(void) { 
    char dest[6]; 
    char source[6]; 

    strcpy(dest,source); 

    while (*dest) { printf("%c",*dest++); } 
    while (*source) {printf("%c",*source++); } 

    return 0; 
} 

Я получаю ошибку времени выполнения. Я подозреваю, что это потому, что strcpy копирует от источника к месту назначения, пока не встретит \0. Однако он не столкнулся с нулевым символом и продолжал копировать из буфера до возникновения ошибки времени выполнения. Чтобы решить эту проблему, я изменил код следующим образом:

#include <stdio.h> 

int main(void) { 
    char dest[6]; 
    char source[6]; 


    memset(dest, '\0', 6*sizeof(dest)); //trying to set dest to '/0' 
    strcpy(dest,source); 

    while (*dest) { printf("%c",*dest++); } 
    while (*source) {printf("%c",*source++); } 

    return 0; 
} 

я получаю следующие ошибки:

prog.c:11:38: error: lvalue required as increment operand

while (*dest) { printf("%c",*dest++); } 
           ^

и

prog.c:11:38: error: lvalue required as increment operand

while (*dest) { printf("%c",*source++); } 
            ^

Почему это происходит?

+3

Эта первая программа [не компилируется] (http://ideone.com/2Zy1hx) по той же причине, что и вторая. Вы уверены, что это источник, который вы использовали? – templatetypedef

+1

Кроме того, вы не можете применять ++ к массивам. :-) – templatetypedef

+3

Скорее, 'dest ++' не является законным кодом C, если 'dest' является массивом. – templatetypedef

ответ

4

Для начала он является исходным массивом, который должен быть нулевой прекращенным, если вы собираетесь скопировать его в других символьных массивах используя стандартную функцию C. strcpy. Таким образом, вместо этого заявления

memset(dest, '\0', 6*sizeof(dest)); 

вы должны по крайней мере написать

memset(source, '\0', 6*sizeof(source)); 
     ^^^^^^    ^^^^^^^ 

Однако даже это утверждение неверно, потому что переписывает память, выделенную для массива. sizeof(source) уже равна 6 байт, как это следует из декларации массива

char source[6]; 

Таким образом, вы должны написать

memset(source, '\0', sizeof(source)); 
        ^^^^^^^^^^^^^ 

На самом деле там было достаточно, чтобы написать либо как

char source[6] = { '\0' }; 

или аналогично

char source[6] = ""; 

или как

char source[6]; 
source[0] = '\0'; 

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

while (*dest) { printf("%c",*dest++); } 

Вместо этого заявления можно было бы написать

for (char *p = dest; *p; ++p) { printf("%c", *p); } 

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

+0

Эта строка: 'memset (источник, '\ 0', 6 * sizeof (source));' НЕ правильно. 'sizeof (source)' is 6, 6 * 6 равно 36, так что это очистит 36 байт, после того как первые 6 выйдут за пределы границы массива. Результатом является неопределенное поведение и может привести к событию сбоя seg. Предложите удалить '6 *' – user3629249

+0

@ user3629249 Вы прочитали весь пост, прежде чем писать свой комментарий? :) –

+0

да, я прочитал весь пост И ваш ответ. Ваш ответ распространяет одну из проблем с кодом, опубликованным OPs. – user3629249

-1

strcpy не является надежной функцией, предпочитайте использовать strncpy.

Ошибка связана с тем, что вы пытаетесь увеличить массив, что является rvalue (т. Е. Константой, вы не можете поместить ее в левую сторону знака =).

Общий подход перебрать массив должны использовать указатель, как так:

char *p = dest; 
while (*p) { printf("%c",*p++); } 
+0

Ухаживаете за пояснением? –

+0

Я не спускал вниз, но 'strncpy' - это не просто более безопасная версия' strcpy'. Это на самом деле делает некоторые очень удивительные вещи по историческим причинам, и, следовательно, это, вероятно, не то, что вы хотите во многих случаях. –

+0

Насколько я помню, обратная сторона strncpy заключается в том, что он не добавляет байт '\ 0', если достигнут максимальный размер, но здесь это не проблема, поскольку он использовал неинициализированные данные и мне показалось, что просто старайтесь манипулировать указателями и памятью. –

1

следующий код полностью компилирует и выполняет требуемую операцию.

Различия между опубликованным кодом и этим комментарием.

#include <stdio.h> // printf() 
#include <string.h> // strcpy() 

int main(void) 
{ 
    char dest[6]; // declared, containing garbage 
    char source[6] = "12345"; // declared, containing the string "12345\0" 

    strcpy(dest,source); 
    // now both arrays contain the string "12345\0" 

    // best to use a 'for()' statement for indexing through an array 
    for(size_t i=0; dest[i]; i++) { printf("%c", dest[i]); } 
    printf("\n"); // output the buffered data to the terminal 
    for(size_t i=0; source[i]; i++) { printf("%c", source[i]);} 
    printf("\n"); // output the buffered data to the terminal 

    // note, the following lines contain a precedence problem in 
    // the increment expressions and 
    // the address of an array declaration cannot be incremented 
    //while (*dest) { printf("%c",*dest++); } 
    //while (*source) {printf("%c",*source++); } 

    //return 0;// with modern C compilers, 
      // this line is not necessary in a 'main()' function 
      // when returning 0 
} // end function: main