реклама на сайте
подробности

 
 
6 страниц V   1 2 3 > »   
Closed TopicStart new topic
> Указатели на строку в С
psL
сообщение Jan 24 2016, 08:04
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 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. Почему так?
Go to the top of the page
 
+Quote Post
amaora
сообщение Jan 24 2016, 10:17
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778



В первом случае нет переменных хранящих адрес массива, чтобы получить &str как во втором случае эту переменную пришлось бы создать и выдать ее адрес.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 24 2016, 10:32
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 24 2016, 10:35
Сообщение #4


Гуру
******

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



QUOTE (amaora @ Jan 24 2016, 12:17) *
В первом случае нет переменных хранящих адрес массива, чтобы получить &str как во втором случае эту переменную пришлось бы создать и выдать ее адрес.

Потому, что в первом примере определена строка, а во втором УКАЗАТЕЛЬ на строку.

А вопрос-то был о другом.
Все три выражения в первом случае это есть одно и тоже, поскольку имя переменной это есть ее адрес, то указание взятия адреса есть масло маслянное. Для масивов адрес массива есть адрес его нулевого элемента, посему допронительное указание взять адрес именно нулевого есть уже масло маслянное для масла маслянного.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
_Ivan_33
сообщение Jan 24 2016, 11:10
Сообщение #5


fpga designer
****

Группа: Свой
Сообщений: 613
Регистрация: 20-04-08
Из: Зеленоград
Пользователь №: 36 928



а почему 2?
а строковый литерал типа
#define MSG "BLA BLA BLA"
?


--------------------
Go to the top of the page
 
+Quote Post
psL
сообщение Jan 24 2016, 11:26
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 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 как во втором случае эту переменную пришлось бы создать и выдать ее адрес.

разве имя массива без индекса не является указателем на первый член этого массива? непонятно.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 24 2016, 11:34
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jan 24 2016, 11:36
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
psL
сообщение Jan 24 2016, 11:42
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390



Цитата(zltigo @ Jan 24 2016, 14:34) *
В этом Вашем-же примере p1 это "указатель на начало массива"? А p2 "указатель на этот указатель". Соответственно это два РАЗНЫХ объекта и имеют "разные числа", что и видно в Вашей-же распечатке. Аминь.
Начните с чтения K&R. Ну ОЧЕНЬ помогает.

Где аминь? Почему p1 == p2 в случае p2 = &str ; при char str[] = "blablabla" ? Без K&R обьяснить можете? laughing.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 24 2016, 11:51
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
amaora
сообщение Jan 24 2016, 12:13
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778



Цитата(psL @ Jan 24 2016, 14:26) *
разве имя массива без индекса не является указателем на первый член этого массива? непонятно.


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

Может стоит разобраться как этот код в памяти располагается, если есть непонимание.
Go to the top of the page
 
+Quote Post
psL
сообщение Jan 24 2016, 12:46
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 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) *
Выражение "имя массива без индекса" имеет тип указателя на элемент массива, значение соответствует адресу первого члена. Но это не переменная-указатель, собственного адреса у этого выражения нет. В таблице символов компилятора есть только переменная "массив", со своим адресом, а вы хотите получить адрес переменной где хранится указатель на "массив", такого нигде нет.

Спасибо. Более-менее понятно.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 24 2016, 12:54
Сообщение #13


.
******

Группа: Участник
Сообщений: 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] );
}

Какой компилятор так умеет извращаться? sm.gif

Сообщение отредактировал GetSmart - Jan 24 2016, 13:06


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
gerber
сообщение Jan 24 2016, 13:03
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 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 не имеет.


--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 24 2016, 13:11
Сообщение #15


Гуру
******

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



Цитата(GetSmart @ Jan 24 2016, 14:54) *
Какой компилятор так умеет извращаться? sm.gif
Любой выполняющий требования стандарта.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

6 страниц V   1 2 3 > » 
Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th August 2025 - 03:47
Рейтинг@Mail.ru


Страница сгенерированна за 0.01404 секунд с 7
ELECTRONIX ©2004-2016