Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700

Почему результат выводится без разыменования указателя?

17.10.2016, 16:11. Показов 1819. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
char *ptr = "hello";
char *ptr это указатель? Указатель. А указатель это переменная которая содержит адрес данных.
Почему тогда при печати printf("%s", ptr); выводится строка? По идее нужно было написать так printf("%s", *ptr); что бы увидеть строку(получить данные указателя). Но так выводит ошибку.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.10.2016, 16:11
Ответы с готовыми решениями:

Почему не происходит разыменования нулевого указателя?
вот думаю, почему сия конструкция не вылетает: #define offsetof(type, member) (size_t)(&(((type*)nullptr)->member))... видимо не...

Почему не выводится результат?
У меня из класса с формой вызывается метод другого класса, в котором проводятся все расчеты: EvenSearch evenSearchMethod = new...

Почему выводится разный результат?
int main(){ int mass={3,5,3,5,3}; int i=0, r=0; for(int i = 0; i < 5; i++) if(mass % 3 == 0) ...

21
1786 / 1036 / 445
Регистрация: 12.05.2016
Сообщений: 2,550
17.10.2016, 16:24
sys_beginner, тогда уже так:
C
1
printf("%c", *ptr);
ptr указывает на первый элемент строки, а printf("%s", ...) выводит элементы начиная с того на который указывает ptr пока не встретит '\0'.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.10.2016, 16:27  [ТС]
shvyrevvg,
При использовании %s printf сама извлекает данные из адреса?
0
1786 / 1036 / 445
Регистрация: 12.05.2016
Сообщений: 2,550
17.10.2016, 16:33
Цитата Сообщение от sys_beginner Посмотреть сообщение
При использовании %s printf сама извлекает данные из адреса?
sys_beginner, да, Вы же ей указали начало, а концом служит '\0'
char *ptr = "hello"; равносильно char ptr[6] = "hello\0";
ptrinf() перебирает элементы пока не встретит нуль.
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
17.10.2016, 16:39
Цитата Сообщение от sys_beginner Посмотреть сообщение
Почему тогда при печати printf("%s", ptr); выводится строка?
C99 Par.7.21.6.1. (s)
If no l length modifier is present, the argument shall be a pointer to the initial
element of an array of character type
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.10.2016, 16:43  [ТС]
shvyrevvg,
Тогда вопрос. Раз уж для хранения литерала требуется указатель, как объяснить следующее:
C
1
char *ptrArr[2] = {"hello", "world"};
Указатель ptrArr указывает на массив с двумя литералами (которые по сути тоже являются указателями. ведь литералы как мы выяснили выше, это указатели). Почему тогда компилятор не требует указать такую запись не просто как указатель, а как указатель на указатель?

Второй пример
C
1
2
3
char *hello = "hello";
char *world = "world";    
char **ptrArrAddr[2] = {hello, world};
Почему не компилируется? hello и world это указатели и должны содержать адрес данных.

А если задать адреса явно, тогда все работает
C
1
2
3
char *hello = "hello";
char *world = "world";    
char **ptrArrAddr[2] = {&hello, &world};
Вопросы:
1. Почему во втором примере для переменных hello и world требуется забирать их адреса, если они уже являются указателями(а как известно указатель уже является адресом).
2. Почему в первом примере создавая массив указателей (учитывая то, что для хранения литерала требуется указатель)
достаточно написать char *ptrArr[2] = {"hello", "world"};. То есть достаточно бывает создать 1 указатель вместо указателя на указатель
0
1786 / 1036 / 445
Регистрация: 12.05.2016
Сообщений: 2,550
17.10.2016, 18:08
sys_beginner, читайте по указателям инфу, что такое указатель на указатель, что такое массив указателей, и т.д.
Цитата Сообщение от sys_beginner Посмотреть сообщение
C
1
char *ptrArr[2] = {"hello", "world"};
Цитата Сообщение от sys_beginner Посмотреть сообщение
Указатель ptrArr указывает на массив
Уверены что не наоборот?

Добавлено через 2 минуты
Цитата Сообщение от sys_beginner Посмотреть сообщение
1. Почему во втором примере для переменных hello и world требуется забирать их адреса, если они уже являются указателями(а как известно указатель уже является адресом).
Во втором примере у Вас массив указателей на указатели, поэтому вы берете адрес указателя.
Цитата Сообщение от sys_beginner Посмотреть сообщение
2. Почему в первом примере создавая массив указателей (учитывая то, что для хранения литерала требуется указатель)
достаточно написать char *ptrArr[2] = {"hello", "world"};. То есть достаточно бывает создать 1 указатель вместо указателя на указатель
В первом примере у вас массив указателей, поэтому все норм.
1
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
17.10.2016, 18:34
Цитата Сообщение от shvyrevvg Посмотреть сообщение
char *ptr = "hello"; равносильно char ptr[6] = "hello\0";
Ничего подобного. В первом случае строковый литерал hello будет размещен в read-only секции в памяти программы, а адрес его первого символа записан в указатель ptr. Операции записи по такой строке нелегальны. Во втором случае литерал hello\0 будет размещен в read-only секции в памяти программы и будет скопирован в выделенную на стеке память переменной ptr. Писать туда можно. Так что ни разу не равносильно.

Обоим участникам обсуждения домашнее задание: сколько символов будет прокопировано в память переменной из этого литерала во втором кейсе?

Цитата Сообщение от sys_beginner Посмотреть сообщение
Указатель ptrArr указывает на массив с двумя литералами
Нет. ptrArr представляет собой массив из 2-х элементов каждый из которых указатель на символ.
Цитата Сообщение от sys_beginner Посмотреть сообщение
Почему не компилируется?
Второй пример не компилируется ровно по этой причине. Оттуда же ответы на остальные вопросы.
1
1786 / 1036 / 445
Регистрация: 12.05.2016
Сообщений: 2,550
17.10.2016, 19:20
Цитата Сообщение от HighPredator Посмотреть сообщение
Обоим участникам обсуждения домашнее задание: сколько символов будет прокопировано в память переменной из этого литерала во втором кейсе?
HighPredator, получается в первом случае на стеке будет указатель, во втором массив целиком. Ну так 6 символов и будет скопировано, разве нет?
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
17.10.2016, 19:42
Цитата Сообщение от shvyrevvg Посмотреть сообщение
Ну так 6 символов и будет скопировано, разве нет?
Нет. 7. Ноль-терминатор дошивается при копировании независимо от того, есть он в литерале или нет. То есть состав строки вообще не анализируется. Поэтому собственно этот код с косяком. Однако, если правильно настроить компилятор, то он вам выругается что мол инициализатор слишком длинный.
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
17.10.2016, 19:59
Цитата Сообщение от sys_beginner Посмотреть сообщение
shvyrevvg,
Тогда вопрос. Раз уж для хранения литерала требуется указатель,
Это бессмысленная формиулировка. Для хранения литерала всегда требуется массив символов соответствующей длины. Этот массив символов не имеет имени и выделяется в статической памяти компилятором.

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

Цитата Сообщение от sys_beginner Посмотреть сообщение
как объяснить следующее:
C
1
char *ptrArr[2] = {"hello", "world"};
Указатель ptrArr указывает на массив с двумя литералами
ptrArr - не указатель. ptrArr - массив. ptrArr - массив из двух указателей типа char *. Каждый их этих char * указателей в массиве будет указывать на свой строковый литерал.

Цитата Сообщение от sys_beginner Посмотреть сообщение
(которые по сути тоже являются указателями. ведь литералы как мы выяснили выше, это указатели).
"Выяснили" неправильно. Строковые литералы - это не указатели.

Цитата Сообщение от sys_beginner Посмотреть сообщение
Почему тогда компилятор не требует указать такую запись не просто как указатель, а как указатель на указатель?
Не понял вопроса. Какой еще "указатель на указатель"? Где?

Цитата Сообщение от sys_beginner Посмотреть сообщение
Второй пример
C
1
2
3
char *hello = "hello";
char *world = "world";    
char **ptrArrAddr[2] = {hello, world};
Почему не компилируется? hello и world это указатели и должны содержать адрес данных.
Да, hello и world - это указатели. Массив же объявлен как содержащий указатели-на-указатели. Налицо явное несоответствие типов.

Цитата Сообщение от sys_beginner Посмотреть сообщение
А если задать адреса явно, тогда все работает
C
1
2
3
char *hello = "hello";
char *world = "world";    
char **ptrArrAddr[2] = {&hello, &world};
Несоответствие типов устранено.
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.10.2016, 20:14  [ТС]
Цитата Сообщение от shvyrevvg Посмотреть сообщение
Уверены что не наоборот?
Думаю да Почитаю ещё раз, спасибо за совет.

Цитата Сообщение от HighPredator Посмотреть сообщение
а адрес его первого символа записан в указатель ptr.
А откуда компилятор знает про символы? Он же ничего про кодировку данных не знает. http://rextester.com/DLG56628

Цитата Сообщение от HighPredator Посмотреть сообщение
Нет. ptrArr представляет собой массив из 2-х элементов каждый из которых указатель на символ.
Если быть до конца точным, то да, согласен

Добавлено через 12 минут
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
ptrArr - не указатель. ptrArr - массив.
Слегка запутался.
Когда объявляется массив, разве переменная которой он присваивается это не указатель на первый элемент?
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
17.10.2016, 20:21
Цитата Сообщение от sys_beginner Посмотреть сообщение
А откуда компилятор знает про символы?
Ему сказали.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.10.2016, 20:22  [ТС]
Цитата Сообщение от HighPredator Посмотреть сообщение
Ему сказали.
А если серьезно?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
17.10.2016, 20:34
Цитата Сообщение от sys_beginner Посмотреть сообщение
Когда объявляется массив, разве переменная которой он присваивается это не указатель на первый элемент?
Нет, разумеется. Массив - это массив. Никаких указателей там нет.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.10.2016, 20:48  [ТС]
TheCalligrapher,
Спасибо. А звездочки после типа уже касаются каждого его элемента на первом уровне вложенности?

Добавлено через 4 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Когда объявляется массив, разве переменная которой он присваивается это не указатель на первый элемент?
Нет, разумеется. Массив - это массив. Никаких указателей там нет.
А почему тогда при печати массива выводится первый его элемент? http://rextester.com/BXXVJ55054
Если переменная которой он присваивается не является указателем на первый элемент
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,217
17.10.2016, 20:57
Цитата Сообщение от sys_beginner Посмотреть сообщение
А почему тогда при печати массива выводится первый его элемент? http://rextester.com/BXXVJ55054
Если переменная которой он присваивается не является указателем на первый элемент
Этот код вообще не является корректным С кодом.

Если посмотреть на диагностические сообщения компилятора, то видно, что он просто видит его как

C
1
char* arr = "Hello";
но это не более чем развеселая студенческая самодеятельность авторов компилятора GCC, никакого отношения к языку С не имеющая.

Если вы хотите, чтобы компилятор GCC вел себя как компилятор языка С, то необходимо указывать параметры -std=... и -pedantic-errors. Например, -std=c11 -pedantic-errors
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.10.2016, 21:07  [ТС]
TheCalligrapher,
Большое спасибо. Все понятно
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
17.10.2016, 21:31
Цитата Сообщение от sys_beginner Посмотреть сообщение
А если серьезно?
А я на полном серьезе Компилятору было объяснено, что некоторые пары символов, начинающихся с обратного слеша нужно интерпретировать специальным образом. \0 \t \n и т.д.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
18.10.2016, 10:17  [ТС]
HighPredator,
Я не совсем про это
Понятие "символ" из области кодировки, так? В литерале char *ptr = "hello"; может быть не hello, каждый символ которого 1 байт, а например, символ состоящий из двух или более байт.
Но как видно кодировка в данном примере не применяется, соответственно компилятор насколько я понимаю ничего не знает о "символах" а работает со строкой как с потоком байт. В связи с этим не могу понять, как именно он определяет какой "символ" идет первым?

Добавлено через 2 минуты
Может просто имеется ввиду, что идет смещение на начало области памяти, на которое указывает char *ptr ?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.10.2016, 10:17
Помогаю со студенческими работами здесь

Почему на label11 выводится не правильный результат?
private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { char chislo = e.KeyChar; ...

Почему выводится не результат, а выражение, которое вводилось?
Здравствуйте подскажите пожалуйста, ввожу следующее выражение (-1 + i)^5: затем жму Enter, после ввожу такую вот команду evalf(%), и...

Результат выполнения цикла for и while не выводится на экран, почему?
Мне нужно что бы прозрачность обекта постепенно уменшалась... Засунул в цикл - а он сам себе обрабатывает, а на экран дает уже готовое, а...

Как работать с элементами двумерного динамического массива через явное разыменования указателя?
Доступ к элементам массива через индексы проходит без труда, а вот с указателями проблема. Как вывести элементы массивы без индексов, а...

Почему не выводится результат выполнения программы. В чём ошибка
Составила программу (условие прилагается). Результат не выводится. Почему? В чём ошибка? Помогите исправить, пожалуйста!


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru