Привет.
Вопрос такой :
Почему указатели типа char не нуждаются в раскрытии.
Например :
void syntax_error(int num)
{
static char *err[] = {
"Нельзя открыть файл\n",
"Ошибка при чтении\n",
"Ошибка при записи\n",
"Некачественный носитель\n"
};
printf("%s", err[num]);
}
казалось бы перед err[num] должен быть оператор *
23 июля 2009 в 10:03
Подмогаев Свят, понимаешь, в функцию ты всегда передаёшь значение, дело только в том значение чего.
по %d функция хочет значение числа и расчитывает что получила именно его в наборе полученых байт, по %s она хочет адрес начала строки, и если транслятор прошёл то при вызове функция будет думать что этот набор полученых ею байт это адрес начала строки.
23 июля 2009 в 3:00
вся проблема сводилась к этому :
"Просто строка – ето адрес первого символа, а другие типи – ето самая ячейка памьяти… Тоесть %s – надо адрес, %d(f, и др.) – надо взять адрес…"
спасибо за разъяснения
23 июля 2009 в 2:00
Тут уже все говорили но возьмусь все ето обьеденить…
Значит так, строка – ето всеравно что масив чаров… если обьявить char *a = "Some string", то для разпечатки всего надо сказать прінтефу, что ето строка – %s. Если ето строка, то есть масив чаров, то надо передать адрес первого елемента. Тогда распечатается все до символа конца строки '\0', он добавляется автоматически в конец строки в даном примере. Если надо один символ – то %с и тогда *а…
char *err[] – ето масив указателей, то есть масив масивов(двумерний)
начало (*err или err[0]) -> "Нельзя открыть файл\n"
*(err+1) илиerr[1]->"Ошибка при чтении\n"
*(err+2) илиerr[2]->"Ошибка при записи\n"
*(err+3) илиerr[3]->"Некачественный носитель\n"
Примерна такова его структура в памяти…
Просто строка – ето адрес первого символа, а другие типи – ето самая ячейка памьяти… Тоесть %s – надо адрес, %d(f, и др.) – надо взять адрес…
22 июля 2009 в 23:00
"во-первых, в 32-битной системе указателю выделяется 4 байта"
согласен, ляпнул не совсем верно
сайзами и пользуюсь…
22 июля 2009 в 22:04
"во-первых, в 32-битной системе указателю выделяется 4 байта"
с тойже степенью достоверности можно говорить что в байте 8 бит, т.е. если вы так говорите то для вас оно скорей всего так и есть, хотя на самом деле есть варианты так что лучше не принимать эту догму а честно пользоваться сайзами.
строка это массив чаров заканчивающийся нулевым символом. под "передать строку" подразумевается передать указатель на первый символ строки. так что принтф по %s расчитывает получить именно указатель на начало строки, а по %d целое.
22 июля 2009 в 22:04
Глеб 'Whatup' Загребалов, транслятор в данном случае тупой и встречая "строка"понимает что это константа и выделяет под неё память в сегменте данных и заполняет значением, точно также как встречая цифры выделяет память под них вне зависимости от того в каком месте встретил.
22 июля 2009 в 22:01
Насчет памяти – если ты инициализируешь указатель СРАЗУ же в его объявлении, то память выделится автоматически:
char *str = "O_o";
Если же потом – нет, и это таки да, чревато. Поправьте, если ошибаюсь.
Алсо, для адресов есть православный спецификатор %p.
22 июля 2009 в 21:02
an†ik
Это понятно )
22 июля 2009 в 20:05
Кристиан Prayer Баринов,
"err[num] – это уже эл-т массива, поэтому звездочка не нужна."
*(err+num) – то же самое, только со звездочкой
22 июля 2009 в 20:02
так… по парядку…
имя переменной – это адрес, ссылка на значение.
указатель – переменная, хранящая адрес, указывающий где хранится значение
тогда при выводе строки с использование шаблона %s, он переходит по адресу, который содержит указатель. а при %d – читает значение переменной.
22 июля 2009 в 20:01
Свят
Извиняюсь, если я не понял тебя
ViLco
Может, я ошибаюсь, но в printf(), как я помню, передавать нужно значение переменной (конечно, строка всегда передается как указатель)
22 июля 2009 в 20:00
то есть для %s передаем указатель , а для %d значение ?
22 июля 2009 в 19:05
во-первых, в 32-битной системе указателю выделяется 4 байта, хотя тип char – всего один.
во-вторых, работа со строками происходит так: от какого-либо адреса до нулекого байта (признак конца строки). наверное в этом и причина
22 июля 2009 в 19:05
Prayer, вы не обижайтесь только, но вы не больше автора похоже понимаете.
Потому что когда парсер встречает %s в шаблоне, он считает что в соответствующем параметре находится указатель на начало строки, а %d – считает что ему подсунули число (в данном случае это число – адрес переменной number)
22 июля 2009 в 19:03
Кристиан Prayer Баринов
К чему выделять память ,если по умолчанию память выделяется в таблице строк ?
"Грубая ошибка: printf("%d",point1)"
причем здесь грубая ошибка, если я специально не указывал перед указателем оператор получение значения по указателю ?
эмс..переменная-то объявлена, а значение – не принципиально.
ты видимо не понял моей мысли.
а мысль в следующем :
в случае с чарами мы в printf() передаем указатель, а случае ином мы этот самый указатель разименовываем
22 июля 2009 в 18:04
> char *point1;
> point1 = "any string";
Примечание: не вижу выделения памяти под указатель. Это неправильно. Выдели память
> int *point1;
> int number;
> point1 = &number;
В point1 ты записываешь адрес переменной number. В чем проблема? Все отлично . Только есть несколько недочетов:
1. Грубая ошибка: printf("%d",point1) печатает не значение переменной point1, а значение ее адреса. Запомни: Си – язык военный. Скажешь ему катить квадратное – покатит. Это тебе не Java с эксептионами
Нужно так: printf("%d",*point1)
2. int number не ининициализирована
Попробуй теперь откампилить вот этот простой примерчик:
int main()
{
int *point1;
int number = 100;
printf("%d\n", number);
point1 = &number; // берем адрес перем number
*point1 = 20; // меняем значение по этому адресу
printf("%d\n", *point1);
printf("%d\n", number); // здесь ты видишь, что оно изменилось
_getch();
return 0;
}
Пример наглядный и показывает, что такое, когда одна переменная (point) содержит адрес другой, и что через это адрес можно менять значение переменной number
22 июля 2009 в 17:01
просто немножко указатели у меня в голове не укладываются))
логика такая :
допустим есть такой код :
void func1(void){
char *point1;
point1 = "any string";
printf("%s",point1);
}
так что получается..мы указателю(адресу) приравниваем строковую константу
а если сделать так
void func1(void){
int *point1;
int number;
point1 = &number;
printf("%d",point1);
}
то получим именно адрес, а не объект на который ссылается данный указатель, в данной частности переменную number.
22 июля 2009 в 16:04
Чтобы было понятнее объясню так:
*err[]- это массив строк (массив указателей на строки)
err[num] – строка (указатель на строку)
22 июля 2009 в 13:02
err[num] – это уже эл-т массива, поэтому звездочка не нужна.
Оператор "*" нужен для взятия значения от адреса! В err[num] это сделал уже скобка
А если хочешь, чтобы было со звездочкой, то скомпиль это:
int main()
{
char *err[] = {
"I love Russia\n",
"USA\n",
"Norway\n",
"I want to be with you\n"
};
for (int i = 0; i < 4; i++)
printf("%s", *(err + i)); // опять адресная арифметика
_getch();
return 0;
}
Поставил латиницу – а то плохо русские буквы отображ
22 июля 2009 в 12:00
char * это не обязательно указатель на элемент типа char.
Это может быть указателем на начало массива из char.
Соответственно с-строки хранятся в виде массивов из char.
И не надо разыменовывать.
Можешь конечно сделать *err[num], но тогда у тебя выводится первый символ.
Например *err[0] == 'Н'