Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
dima123123
0 / 0 / 0
Регистрация: 14.11.2013
Сообщений: 19
1

Непонятное поведение printf()

12.08.2016, 10:36. Просмотров 845. Ответов 19
Метки нет (Все метки)

Доброго времени суток всем. Недавно начал изучать си и возникло непонимание происходящего в программе.
Пишу cgi скрипт. Подключил библиотеку cgi-bin, скомпилировал все это дело, используя свою программу и статическую библиотеку, созданную через make.
Вот одна из функций библиотеки:
char *find_val(LIST *head, char *key);
Функция, исходя из написанного, возвращает УКАЗАТЕЛЬ на область памяти, в которую записана строка.
Соответственно, я в своем коде пишу:
Код
    LIST *input = cgi_input_parse();
    char *key = "test";
    char *str = find_val(input, key);
    printf("the value of the param \"test\" is the %s", str);
При обращении к cgi-скрипту POST-запросом из PHP (библиотека curl) я подаю строку test=xxx (неважно, что там)
Но когда я обращаюсь к такой программе, написанной выше, я ожидаю увидеть АДРЕС ячейки памяти, а не значение XXX, потому что я создал переменную-указатель на строку. По сути, чтобы вывести значение, я должен написать:
Код
printf("the value of the param \"test\" is the %s", *str);
Таким образом я произвошу развертку (не помню, как называется) и по указателю получаю значение, записанное в ячейку памяти.
По факту я получаю ошибку при компиляции, мол, неверный тип, ожидается строка а подан аргумент типа int. Тогда я меняю %s на %d, запускаю прогу и вижу "the value of the param "test" is the 72". Это даже не значение переменной, да и не адрес ячейки памяти. Это вообще чертовщина какая-то. Причем возвращается одно и то же значение (значит, это не мусор).
Т.к. си я изучаю первый день, я явно ошибаюсь. Но где? Поясните, пожалуйста. Мануалы читал, считал, что все понимаю, но этот пример сбил с толку.
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.08.2016, 10:36
Ответы с готовыми решениями:

Непонятное поведение функции atol
добрый день, конвертирую строку str4 к long int использую функцию atol и смотрю в дебаге получаю...

Непонятное поведение поведение TIM6 на STM32f4discovery
Вводные данные: SYSCLK=168Мгц; AHB Pressotir=1; APB1 Pressotir=4; TIM6_Pessotir=3; Т.о....

Printf выводит непонятное число вместо требуемого
Здравствуйте. Совсем недавно начал изучать С++, и натолкнулся на такую проблему, нигде не могу...

Непонятное поведение
Всем привет! В книге "Прата - Язык программирования C++. Лекции и управжения 2011" нашёл вот такой...

Непонятное поведение ОС
Здрасте! Купил новый комп, а он загружается через раз (чаще через несколько раз), выключается...

19
Papayaved
75 / 75 / 8
Регистрация: 24.09.2015
Сообщений: 335
12.08.2016, 10:46 2
dima123123,
C
1
2
3
printf("the value of the param "test" is the %s", str); // - строка
printf("the value of the param "test" is the %x", (int)str); // - адрес первой буквы
printf("the value of the param "test" is the %x", *str); // - ASCII коде первой буквы
%s - распечатывает массив str в виде букв, пока не встретить символ конца строки, т.е. 0
1
nimazzzy
Заблокирован
12.08.2016, 10:50 3
Лучший ответ Сообщение было отмечено dima123123 как решение

Решение

Цитата Сообщение от dima123123 Посмотреть сообщение
Т.к. си я изучаю первый день, я явно ошибаюсь. Но где?
%s это сокращение от string. Строк как отдельного типа данных в С не существует. Строка там - адрес набора char'ов, который нулем завершается. Поэтому, чтобы вывести строку, надо передать адрес ее начала. И спецификатором формата указать, что переданный адрес, это адрес массива char - %s.
*str - это ты взял первый char по адресу str, а не "значение строки".
Чтобы вывести адрес, а не рассматривать переданный аргумент как строку, надо использовать %p (pointer).
1
dima123123
0 / 0 / 0
Регистрация: 14.11.2013
Сообщений: 19
12.08.2016, 10:51  [ТС] 4
Так ведь str это не строка, а указатель на строку (char *str), поэтому должен выводиться адрес ячейки памяти?
0
Papayaved
75 / 75 / 8
Регистрация: 24.09.2015
Сообщений: 335
12.08.2016, 10:54 5
dima123123, а как тогда строку? Такая команда специально для печати массива char сделана - для печати цифр другие команды есть
0
nimazzzy
Заблокирован
12.08.2016, 10:56 6
Цитата Сообщение от Papayaved Посмотреть сообщение
printf("the value of the param "test" is the %x", (int)str); // - адрес первой буквы
Для задачи вывода адреса уже существуте спецификатор %p.

Добавлено через 1 минуту
Цитата Сообщение от dima123123 Посмотреть сообщение
Так ведь str это не строка, а указатель на строку (char *str), поэтому должен выводиться адрес ячейки памяти?
%s явно указывает, что ты хочешь вывести саму строку, а не адрес.
0
LFC
730 / 535 / 416
Регистрация: 17.09.2015
Сообщений: 1,598
12.08.2016, 11:04 7
Цитата Сообщение от dima123123 Посмотреть сообщение
и вижу "the value of the param "test" is the 72".
у вас в строке первый элемент H,вот его числовой код и считывает printf со спецификатором %d. Если применить спецификатор %с - выведет на экран сам символ H. Вначале вы применяли спецификатор %s - и считывалась вся строка.
0
dima123123
0 / 0 / 0
Регистрация: 14.11.2013
Сообщений: 19
12.08.2016, 11:06  [ТС] 8
Так-с, вроде все прояснилось, спасибо большое!
Теперь меня смущает эта строка. Я написал её как-то не брав во внимание детали (привык к скриптовым языкам):
Код
 char *key = "test";
Если бы не было указателя, то была бы ошибка, т.к. правильно строка задается как массив char'ов, т.е. key[4] = "test";
Но тогда что в данном случае происходит, если это нормально работает? Создается ячейка памяти в 4 байта (или даже 5 (а может) с конечным символом замыкания области - нулем (или это вообще бит)?), а затем переменной key присваивается адрес этой ячейки?
Тогда почему не работает вот это:
Код
    char key[4] = "test", *keyref;
    keyref = &key;
Потому что компилятор не понимает, адрес чего заносить в keyref? Что тогда, адреса массивов (или строк) можно получать только через calloc/malloc?
0
LFC
730 / 535 / 416
Регистрация: 17.09.2015
Сообщений: 1,598
12.08.2016, 11:17 9
Цитата Сообщение от dima123123 Посмотреть сообщение
char key[4] = "test",
здесь вы пытаетесь пятый элемент(размером в один байт) символьного массива key инициализировать строкой из четырех символов.Не влазит.
0
LFC
730 / 535 / 416
Регистрация: 17.09.2015
Сообщений: 1,598
12.08.2016, 11:23 10
извиняюсь,тупанул
dima123123,не читайте мое предыдущее))
1
nimazzzy
Заблокирован
12.08.2016, 11:28 11
LFC, не, это я между форумными вкладками заблудился. При определении строки на стеке присваивание валидно
Под строку
Цитата Сообщение от dima123123 Посмотреть сообщение
"test"
должен быть выделен буфер в 5 символов, так как в конце еще нулевой символ.
0
LFC
730 / 535 / 416
Регистрация: 17.09.2015
Сообщений: 1,598
12.08.2016, 11:28 12
C
1
keyref = key;
имя массива само по себе является указателем, & не надо ставить.
0
nimazzzy
Заблокирован
12.08.2016, 11:29 13
Цитата Сообщение от dima123123 Посмотреть сообщение
Потому что компилятор не понимает, адрес чего заносить в keyref?
Не понял, в чем у тебя проблема.
C
1
2
3
    char s[5] = "test";
    char *keyref = s;
    printf("%s\n", keyref);
0
dima123123
0 / 0 / 0
Регистрация: 14.11.2013
Сообщений: 19
12.08.2016, 11:29  [ТС] 14
Да, я только собирался написать, что вы окончательно меня запутали. Ладно. строка задается нормально, так почему указатель на первый байт области памяти со строкой "test" не задается?
keyref = &key при компиляции выдает:
warning: assignment from incompatible pointer type [enabled by default]
keyref = &key;
0
nimazzzy
Заблокирован
12.08.2016, 11:30 15
Цитата Сообщение от LFC Посмотреть сообщение
имя массива само по себе является указателем, & не надо ставить.
А это все эквивалентно: key, &key, &key[0]
0
dima123123
0 / 0 / 0
Регистрация: 14.11.2013
Сообщений: 19
12.08.2016, 11:35  [ТС] 16
Спасибо за разъяснения!
В общем, какой-то кошмар, буду разбираться с этими многочисленными подводными камнями.
Надоел вот python/php, захотелось чего-нибудь хардкорного и более низкоуровнего что ли.
А что все-таки означает это?
Код
char *key = "test"
0
LFC
730 / 535 / 416
Регистрация: 17.09.2015
Сообщений: 1,598
12.08.2016, 11:36 17
Цитата Сообщение от nimazzzy Посмотреть сообщение
А это все эквивалентно: key, &key, &key[0]
не,ругается на вариант keyref = &key;
warning: assignment from incompatible pointer type|
0
nimazzzy
Заблокирован
12.08.2016, 11:42 18
Цитата Сообщение от dima123123 Посмотреть сообщение
char *key = "test"
Переменная-указатель key хранит адрес строки "test". Но правильно писать:
const char *key = "test";
Потому что строка эта неизменяемая.
1
LFC
730 / 535 / 416
Регистрация: 17.09.2015
Сообщений: 1,598
12.08.2016, 11:46 19
Цитата Сообщение от dima123123 Посмотреть сообщение
так почему указатель на первый байт области памяти со строкой "test" не задается?
я ж уже писал
keyref = key;
(без &)
и keyref и key указывают на одну и ту же область памяти
0
nimazzzy
Заблокирован
12.08.2016, 11:47 20
Цитата Сообщение от LFC Посмотреть сообщение
не,ругается на вариант keyref = &key;
Warning не меняет того, что keyref будет тем же, что и key Я против такой записи, но сколько себя помню, она работала.
0
12.08.2016, 11:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.08.2016, 11:47

Непонятное поведение процедуры
Добрый день уважаемый форумчане. Имеется процедура, она работает с string_grid, парой...

Непонятное поведение системы
ОС: MW 10 Home 64-bit Processor^Intel(R) Core(TM) i7-6700 CPU 3.40 GHz Core: 32675MB...

Непонятное поведение List
class Program { static void Main(string args) { var list = new...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru