|
|
  |
Указатели на строку в С |
|
|
|
Jan 24 2016, 08:04
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390

|
В Си есть два способа определения строки: Код char str[] = "string"; void* p1= str; void* p2=&str; void* p3=&str[0];
printf("%p\n%p\n%p\n",p1,p2,p3);
$ a.out 0xbfaa14c5 0xbfaa14c5 0xbfaa14c5
char* str = "string"; void* p1= str; void* p2=&str; void* p3=&str[0];
printf("%p\n%p\n%p\n",p1,p2,p3);
$ a.out 0x80488bc 0xbfc25c78 0x80488bc В первом случае p1 равен p2. Почему так?
|
|
|
|
|
Jan 24 2016, 10:32
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(psL @ Jan 24 2016, 10:04)  В Си есть два способа определения строки: Да, но они другие. Эти способы - "abcd" и { 'a', 'b', 'c', 'd','\0'}. Вы же объявили строку одним и тем же способом, более того - в обоих случаях вы продемонстрировали неявное приведение массива к указателю на его первый элемент. Просто во втором случае вы это приведение сделали при объявлении переменной str, а в первом - при объявлении указателей px. В первом случае у вас str - это массив. Во втором случае у вас массив имени не имеет, но существует переменная str, хранящая указатель на его первый элемент.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 24 2016, 10:35
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (amaora @ Jan 24 2016, 12:17)  В первом случае нет переменных хранящих адрес массива, чтобы получить &str как во втором случае эту переменную пришлось бы создать и выдать ее адрес. Потому, что в первом примере определена строка, а во втором УКАЗАТЕЛЬ на строку. А вопрос-то был о другом. Все три выражения в первом случае это есть одно и тоже, поскольку имя переменной это есть ее адрес, то указание взятия адреса есть масло маслянное. Для масивов адрес массива есть адрес его нулевого элемента, посему допронительное указание взять адрес именно нулевого есть уже масло маслянное для масла маслянного.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 24 2016, 11:26
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390

|
Цитата(Сергей Борщ @ Jan 24 2016, 13:32)  Да, но они другие. Эти способы - "abcd" и { 'a', 'b', 'c', 'd','\0'}. чем отличается = { 'a', 'b', 'c', 'd','\0'} от = "abcd" ? пмсм: ничем. Код const char str[] = { 's','t','r','i','n','g', 0 }; void* p1= str; void* p2=&str; void* p3=&str[0];
printf("%p\n%p\n%p\n",p1,p2,p3); $a.out 0xbff1a729 0xbff1a729 0xbff1a729 Почему указатель на начало массива p1 и указатель на этот указатель имеют одно и тоже значение? Почему не вот так работает? Код const char str[] = { 's','t','r','i','n','g', 0 }; void* p1= str; void* p2=&p1; //&str; void* p3=&str[0];
printf("%p\n%p\n%p\n",p1,p2,p3); $a.out 0xbf88cc09 0xbf88cc04 0xbf88cc09 Цитата(_Ivan_33 @ Jan 24 2016, 14:10)  а почему 2? а строковый литерал типа #define MSG "BLA BLA BLA" ? ну может и больше. Интересуют эти 2. В вашем примере строка не будет создаваться программой вплоть до char* str=MSG , например Цитата(amaora @ Jan 24 2016, 13:17)  В первом случае нет переменных хранящих адрес массива, чтобы получить &str как во втором случае эту переменную пришлось бы создать и выдать ее адрес. разве имя массива без индекса не является указателем на первый член этого массива? непонятно.
|
|
|
|
|
Jan 24 2016, 11:34
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (psL @ Jan 24 2016, 13:26)  Почему указатель на начало массива p1 и указатель на этот указатель одно и тоже число? С какого бодуна? Вы сами-же на себя написали опровержение: QUOTE CODE void* p1= str; void* p2=&p1; //&str; void* p3=&str[0];
printf("%p\n%p\n%p\n",p1,p2,p3); $a.out 0xbf88cc09 0xbf88cc04 0xbf88cc09 В этом Вашем-же примере p1 это "указатель на начало массива"? А p2 "указатель на этот указатель". Соответственно это два РАЗНЫХ объекта и имеют "разные числа", что и видно в Вашей-же распечатке. Начните с чтения K&R. Ну ОЧЕНЬ помогает. Аминь.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 24 2016, 11:36
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(psL @ Jan 24 2016, 18:26)  чем отличается = { 'a', 'b', 'c', 'd','\0'} от = "abcd" ? пмсм: ничем. Таки отличается. Код void foo1( char* s ); void foo2( char c );
void foo3( int i ) { foo1( "1234"); foo2( "ABCD"[i] ); } а вот с { 'a', 'b', 'c', 'd','\0'} такой фокус не проходит.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Jan 24 2016, 11:51
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (psL @ Jan 24 2016, 13:42) * Без K&R обьяснить можете? laughing.gif Могу. Вот Вам УЖЕ был дан ответ: QUOTE Все три выражения в первом случае это есть одно и тоже, поскольку имя переменной это есть ее адрес, то указание взятия адреса есть масло маслянное. Для масивов адрес массива есть адрес его нулевого элемента, посему допронительное указание взять адрес именно нулевого есть уже масло маслянное для масла маслянного. Но, очевидно, что для понимания Вам придется начать с букваря для первого класса и вообще научится читать. После чего уже сможете читать в том числе и K&R и уже подумать и понять что делает операнд '=' и что делает операнд '&' получив адрес обьекта.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 24 2016, 12:13
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Цитата(psL @ Jan 24 2016, 14:26)  разве имя массива без индекса не является указателем на первый член этого массива? непонятно. Выражение "имя массива без индекса" имеет тип указателя на элемент массива, значение соответствует адресу первого члена. Но это не переменная-указатель, собственного адреса у этого выражения нет. В таблице символов компилятора есть только переменная "массив", со своим адресом, а вы хотите получить адрес переменной где хранится указатель на "массив", такого нигде нет. Может стоит разобраться как этот код в памяти располагается, если есть непонимание.
|
|
|
|
|
Jan 24 2016, 12:46
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390

|
Цитата(zltigo @ Jan 24 2016, 14:51)  Все три выражения в первом случае это есть одно и тоже, поскольку имя переменной это есть ее адрес, то указание взятия адреса есть масло маслянное. Для масивов адрес массива есть адрес его нулевого элемента, посему допронительное указание взять адрес именно нулевого есть уже масло маслянное для масла маслянного. Но, очевидно, что для понимания Вам придется начать с букваря для первого класса и вообще научится читать... да это какая-то петросянщина маслом масляная. Можете кратко и грамотно безграмотному мне обьяснить? Без букваря, петросяна и тд ? Код char s[]="abc"; void* p1 = s; void* p2 = &s; void* p3 = &p1; Почему равны p1 и p2? Почему не равны p2 и p3? Цитата(amaora @ Jan 24 2016, 15:13)  Выражение "имя массива без индекса" имеет тип указателя на элемент массива, значение соответствует адресу первого члена. Но это не переменная-указатель, собственного адреса у этого выражения нет. В таблице символов компилятора есть только переменная "массив", со своим адресом, а вы хотите получить адрес переменной где хранится указатель на "массив", такого нигде нет. Спасибо. Более-менее понятно.
|
|
|
|
|
Jan 24 2016, 12:54
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Wow! Индекс разрешили применять к rvalue? Цитата(SSerge @ Jan 24 2016, 15:36)  Таки отличается. Код void foo1( char* s ); void foo2( char c );
void foo3( int i ) { foo1( "1234"); foo2( "ABCD"[i] ); } Какой компилятор так умеет извращаться?
Сообщение отредактировал GetSmart - Jan 24 2016, 13:06
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 24 2016, 13:03
|
Знающий
   
Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088

|
Цитата(psL @ Jan 24 2016, 15:46)  Можете кратко и грамотно безграмотному мне обьяснить? Без букваря, петросяна и тд ? Код char s[]="abc"; void* p1 = s; void* p2 = &s; void* p3 = &p1; Почему равны p1 и p2? Почему не равны p2 и p3? Вы присваиваете УКАЗАТЕЛЮ p1 ЗНАЧЕНИЕ массива символов s - поэтому происходит неявное преобразование имени массива s в ссылку на него, то есть в &s. В случае p2 это написано явно. Поэтому значения p1 и p2 равны. А p3 содержит АДРЕС переменной p1, поэтому никакого отношения к ЗНАЧЕНИЮ переменной p1 не имеет.
--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|