2016-02-20 3 views
8

Я хотел перенести элементы из строки в другую строку и, следовательно, написал следующую программу. Первоначально я думал, что цикл for должен выполняться до тех пор, пока не будет скопирован символ NULL (включая его i.e). Но в этом коде цикл for завершается, если найден NULL-символ (т. Е. Еще не скопирован), но он все еще способен отображать строку, в которой были скопированы элементы. Как это возможно, если вначале нет символа NULL?Копирование элементов из одного массива символов в другой

#include<stdio.h> 
#include<stdlib.h> 

int main() 
{ 
    char temp[100], str[100]; 
    fgets(str, 100, stdin); 
    int i; 
    for(i = 0; str[i]!='\0'; i++) 
    { 
     temp[i] = str[i]; 
    } 
    puts(temp); 
    return 0; 
} 
+3

'NULL' - макрос с константой указателя _null. Здесь это не имеет значения. Вы имеете в виду символ ASCII 'NUL' или' nul' с целым значением '0'. – Olaf

+0

Читайте о 'strcpy'. –

+1

@Pete Becker Я думаю, что это ОЧЕНЬ вероятно будет чем-то вроде домашней/учебной проблемы (* i.e. * предназначено/предназначено для того, чтобы сделать одно ** осведомленным ** о проблемах с копированием строк). Просто говорить кому-то, что нужно читать о 'strcpy', не помогает понять это. – Tersosauros

ответ

7

void puts(const char *) функция зависит от size_t strlen(const char *) и выхода этой функции undefined когда нет нулевого терминатора в переданном аргументе (см this answer). Таким образом, в вашем случае strlen внутри puts, вероятно, нашел значение 0 рядом с вашим массивом в памяти, что привело к правильному поведению puts, однако это не всегда так, как оно не определено.

3

Когда вы объявляете char temp[100], не инициализируя его ничем, он просто берет неинициализированную память. Эта память может быть любой. Например, следующая программа будет выписывать начальное содержание, что, как целые числа:

#include<stdio.h> 
#include<stdlib.h> 

int main() 
{ 
    char temp[100]; 
    int i; 
    for(i = 0; i < 100 ; i++) 
    { 
     fprintf(stdout, "%d ", temp[i]); 
    } 
    return 0; 
} 

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

88 -70 43 81 -1 127 0 0 88 -70 43 81 -1 127 0 0 1 0 0 0 0 0 0 0 112 -70 43 81 -1 127 0 0 0 64 -108 14 1 0 0 0 72 50 -13 110 -1 127 0 0 -128 -70 43 81 -1 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 -70 43 81

88 90 72 88 -1 127 0 0 88 90 72 88 -1 127 0 0 1 0 0 0 0 0 0 0 112 90 72 88 -1 127 0 0 0 -96 119 7 1 0 0 0 72 18 72 105 -1 127 0 0 -128 90 72 88 -1 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 90 72 88

88 -6 -79 87 -1 127 0 0 88 -6 -79 87 -1 127 0 0 1 0 0 0 0 0 0 0 112 -6 -79 87 -1 127 0 0 0 0 14 8 1 0 0 0 72 34 57 104 -1 127 0 0 -128 -6 -79 87 -1 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 -6 -79 87

Что, скорее всего, происходит то, что вашей ненулевой завершающей строки случайного завершающий нуль в силе того, что temp[strlen(str)] является , случайно, \0.

+1

Печать этих переменных является неопределенным поведением –

+0

@Giorgi Как так? AFAIK, определено, что я получаю 100 байт, но значения этих байтов не определены. Они должны быть безопасными для печати, но никогда не гарантируется, что они собой представляют. – yaakov

+2

Ни о чем не читайте о понятии неопределенного поведения. Чтение неинициализированных переменных - UB. –

7

Здесь вход и выход на моем компьютере:

0 
0 
絯忐` 

Process returned 0 (0x0) execution time : 1.863 s 
Press any key to continue. 

Смотрите мусор "絯 忐`"? Это неопределенное поведение. Ваша программа работает хорошо, потому что вы (un) повезло.

Опять же, неопределенное поведение не заслуживает много обсуждение.

+3

Я отправился в +1, пока не прочитал эту последнюю строку: ** «Неопределенное поведение не заслуживает обсуждения.» ** «** Хотя это правда, OP был« (un) повезло », поскольку вы Положим, я думаю, что не могу сказать, что ** неопределенное поведение ** не отвечает на вопрос правильно *. – Tersosauros

+1

Все и все может случиться, когда происходят неопределенные действия. Как K & R мудро указывают, «если вы не знаете, как это делается на разных машинах, эта невинность может помочь защитить вас». Поэтому я думаю, что лучше не обсуждать неопределенное поведение. –

Смежные вопросы