c символьные массивы и указатели - PullRequest
2 голосов
/ 13 ноября 2011
#include<stdio.h>
int main(){

char a[6],*p;

a[0]='a';
a[1]='b';
a[2]='c';
a[3]='4';
a[4]='e';
a[5]='p';
a[6]='f';
a[7]='e';
printf("%s\n",a);
printf("printing address of each array element");
p=a;

printf("%u\n",&p[0]);
printf("%u\n",p+1);
printf("%u\n",a+2);
return 0;
}

Вывод выглядит следующим образом ...

anusha@anusha-laptop:~/Desktop/prep$ ./a.out
abc4epfe
printing address of each array element3216565606
3216565607
3216565608

Когда я объявил массив как char a[6], почему он позволяет мне присвоить значение в a[7]?Не нужно ли добавлять к последнему элементу нулевой символ?

Также p = a => p содержит адрес первого элемента массива char a.Я не понимаю, как правильно ставить '&' перед адресом (p[0]).&p[0] означает адрес адреса первого элемента a, который не имеет никакого смысла, по крайней мере для меня.

Почему он печатает правильный вывод?

Ответы [ 6 ]

9 голосов
/ 13 ноября 2011

Вы только что вызвали неопределенное поведение. Нет смысла рассуждать о записи за пределами массива. Только не делай этого.

&p[0] означает адрес адреса первого элемента a[], который не имеет смысла

Нет, это совершенно разумно. Ваше описание прекрасно описывает, что происходит. &p[0] совпадает с p, что совпадает с a. Когда вы пишете p[0], вы разыменовываете указатель. Затем, когда вы пишете &p[0], вы берете адрес этой переменной и возвращаетесь к тому, с чего начали, p.

5 голосов
/ 13 ноября 2011

Наибольший допустимый индекс a равен 5, поэтому вы пишете за пределами массива на два, и да, ему все еще нужен терминатор NULL. Тот факт, что это сработало, было просто совпадением; запись вне границ массива - неопределенное поведение. Это может сработать, может привести к поломке компьютера, купить пиццу с помощью кредитной карты или что-то совершенно другое. Вы понятия не имеете, что он будет делать, поэтому просто не делайте этого.

2 голосов
/ 13 ноября 2011

Когда я объявил массив как char a [6], почему он позволяет мне присвоить значение в [7]?

Потому что ты сказал это сделать. Ты босс. Если вы скажете ему прыгнуть со скалы, он может.

Не нужно ли добавлять к последнему элементу нулевой символ?

Это не строка, это массив символов. Ему не нужен ноль в конце, если вы не хотите рассматривать его как строку. Передавая его через спецификатор %s в printf, вы рассматриваете его как строку, поэтому вам нужно добавить ноль в конце, в противном случае вы передаете что-то, что не является строкой через спецификатор формата, который требует строку.

Также p = a => p содержит адрес первого элемента массива символов a. Я не понимаю, как правильно ставить '&' перед адресом (p [0]). & p [0] означает адрес адреса первого элемента, который не имеет никакого смысла, по крайней мере для меня.

Работает так:
p - указатель на первый элемент.
&p - адрес указателя.
p[0] - первый элемент в массиве, на который указывает указатель.
&p[0] - это адрес первого элемента в массиве, на который указывает указатель.

Почему печатается правильный вывод?

Удача. Скорее всего, реализация, будучи 32-битным (4 байта), не могла сделать ничего полезного с двумя байтами после 6-байтового массива. Таким образом, он округлил его до 8 байтов, чтобы следующая вещь после него начиналась с четной 32-битной границы. Таким образом, вы использовали два байта, которые реализация ни для чего не использовала.

2 голосов
/ 13 ноября 2011

когда я объявил массив как char a [6], почему он позволяет мне присвоить значение в [7]?

потому что C и C ++ не заботятся, для массивов нет проверки границ.

Не нужно ли добавлять нулевой символ для последнего элемента?

нет. например когда вы объявляете массив, скажите char a [7]; Вы говорите компилятору, что хотите семь байтов - ни больше, ни меньше. однако, если вы попытаетесь получить доступ за пределами массива, это ваша проблема.

Я не понимаю, как правильно помечать «&» перед адрес (отмечен p [0]). «& p [0]» означает адрес первого адреса элемент [], который не имеет смысла, верно? Как получается, что печать правильный вывод?

если вы пишете p[0], вы ссылаетесь на значение массива, например, p. если int p[2] = {1,2};, то p[0] равно 1 если вы напишите &p[0], вы получите адрес p [0], который в основном совпадает с p + 0

1 голос
/ 13 ноября 2011

Позволяет вам присвоить значение на a[7], потому что вам повезло. Это неопределенное поведение. Смотрите здесь: http://ideone.com/ntjUn

Ошибка сегментации!

0 голосов
/ 13 ноября 2011

Надеюсь, это немного поможет вам в понимании взаимосвязи массива и указателя:

a[i] == *(a+i) == *(i+a) == i[a]
...