#c #pointers
#c #указатели
Вопрос:
1)
int main()
{
int *j,i=0;
int A[5]={0,1,2,3,4};
int B[3]={6,7,8};
int *s1=A,*s2=B;
while(*s1 = *s2 )
{
for(i=0; i<5; i )
printf("%d ", A[i]);
}
}
2)
int main()
{
char str1[] = "India";
char str2[] = "BIX";
char *s1 = str1, *s2=str2;
while(*s1 = *s2 )
printf("%s ", str1);
}
Второй код работает нормально, тогда как первый код приводит к некоторой ошибке (возможно, ошибка сегментации). Но как переменная указателя s2 в программе 2 работает нормально (т.е. до конца строки), но не в программе 1, где она выполняется бесконечно….
Кроме того, во второй программе переменная s2 не будет увеличиваться сверх длины массива?
Ответ №1:
Особенность строк в C заключается в том, что у них есть специальный символ, который отмечает конец строки. Это ''
символ. Этот специальный символ имеет нулевое значение.
Во второй программе имеющиеся у вас массивы включают символ-терминатор, и поскольку он равен нулю, он обрабатывается как «false» при использовании в логическом выражении (например, условие в вашем while
цикле). Это означает, что ваш цикл во второй программе будет копировать символы вплоть до символа-терминатора включительно, но поскольку это «false», цикл завершится.
В первой программе такого терминатора нет, и цикл будет продолжаться и выходить за пределы, пока он просто случайно не найдет ноль в памяти, из которой вы копируете. Это приводит к неопределенному поведению, которое является частой причиной сбоев.
Таким образом, разница заключается не в том, как обрабатываются указатели, а в данных. Если вы добавите ноль в конец исходного массива в первой program ( B
), то он также будет работать хорошо.
Ответ №2:
В str2 вы назначили строку. Это означает, что будет конец строки (» или NULL), из-за чего, когда вы увеличите Str2 и он достигнет конца строки, он вернет null и, следовательно, ваш цикл прервется.
А с целочисленным указателем нет конца строки. вот почему он переходит в бесконечный цикл.
Ответ №3:
Иоахим дал хорошее объяснение терминального символа строки
на языке C.
Еще одна вещь, о которой следует помнить при работе с указателем, — это арифметика указателей.
Арифметическая единица для указателя — это размер указываемого объекта.
С char *
указателем с именем charPtr
в системе, где char хранятся в 1 байте, выполнение charPtr
увеличит значение в charPtr на * 1 (1 байт), чтобы он мог указывать на следующий символ в памяти.
С int *
указателем с именем intPtr
в системе, где int хранятся в 4 байтах, выполнение intPtr
увеличит значение в IntPtr на 4 (4 байта), чтобы оно было готово указывать на следующий int в памяти.