Чистый СИ. Указатели.

nerezus

Вселенский отказник
ну дык ошибка - вот и падает. Память то не выделена.
 

Pigmeich

Новичок
Re: Чистый СИ. Указатели.

Короче, полный разбор.
с вас $50
Автор оригинала: cDLEON
...
Код:
void
func(char *str) {
[code]Функция которая ничего не возвращает (void), принимает переменную в которой содержиться адрес на первый символ строки
char *str2,*str3,*str4;
Код:
Объявляем что у нас есть три переменные с кривыми названиями (вообще-то при объявлении стоит сразу инициализировать)
*str2=++*str;
Код:
приоритет у '*' и '++' одинаковый приоритет. У '=' меньше.
Сначала мы разыменовываем str2 (в левой части у нас указатель фиг знает на что - str2 никогда не был инициализирован и может указывать хоть на Билл Гейтса).
Потом производиться увеличение по указателю str.
Сначала вычисляется *str - это 'a'. 'a' - это литерал, значение, но не переменная, у нее нет адреса в памяти.
Потом мы делаем ++'a'. Но '++' хочет увеличить переменную на 1, а 'a' не переменная как мы помним.
Ну после всего этого осталось лишь присвоить правую часть левой.
*str3=*(str+2);
Код:
Сначала мы разыменовываем str3 (указывает на Билла Гейтса, как мы помним).
Затем присваем куску памяти с Биллом Гейтсом 3 символ исходной строки (первый - str, второй str + 1)
*str4=*str3-*str2;
Код:
Сначала мы разыменовываем str4 (на Билла Гейтса).
Присваем Биллу разницу char на которые указывают str3 и str2
printf("%p",str4);
}
Код:
ну тут просто печатаем str в представлении для указателя (обычно, это шестнадцатиричнаяя запись с лидирующими ноликами)
Еще вопросы?

Точно не хотите посмотреть на
Код:
template<class T>
struct all_t{
public:
	T& container;
	all_t(T& toFill)
		: container(toFill)
	{
	}
};

template<class T>
all_t<T> All(T& toFill){
	return all_t<T>(toFill);
}
 
template<class T>
ostream& operator << (ostream& os, all_t<T> wraped){
	for(T::const_iterator it = wraped.container.begin(); it != wraped.container.end(); ++it){
		os.width(4);
		os << right << *it << ' ';
	}
	return os;
}
 

Pigmeich

Новичок
Сергей Тарасов
да просто для сравнения, что делает код у ТС и этот. Указатели - только начало для плюсов.
 

nerezus

Вселенский отказник
Pigmeich
может ему плюсы нахрен не нужны? ) А если я сейчас код жабы приведу? )
 

Pigmeich

Новичок
nerezus
ну тогда я отвечу питоном и шарпом ).

А про ТС, я думаю, он имел в виду именно плюсы - хотя фиг его знает зачем Си може понадобиться.
 

Alexandre

PHPПенсионер
Pigmeich зачет, только вот код на С++ зачем, Си же просили.

-~{}~ 17.12.07 19:21:

хотя фиг его знает зачем Си може понадобиться
многие прооекты на сях живут... пхп, аппач, гникс, лигхташтипипи
 

cDLEON

Онанист РНРСlub
Pigmeich
Ну, впринципе, я всё понил до вашего сообщения.
Но всё равно, спасибо, что разжевали )))
А пра ваш код...Я действительно просил чистый СИ. А не СИ++, к тому же я ни хрена не понял что этот код делаеД )
 

Pigmeich

Новичок
cDLEON
он позволяет любой STL контейнер распечать следующей простой строчкой:

Код:
cout << All(Vector);
Лично мне было надо для отладки, вот я его и накидал.
 

cDLEON

Онанист РНРСlub
Код:
void 
test(char *str) {
	char tmp;
	int i=0;
	while(*str) {
		i++;
		//Здесь присваиваем переменной тмп присваиваем символ, 
		//на который сейчас указывает указатель стр. Там же всё это дело и обваливается.
		tmp=*str;
		printf("%s %s %i\n",str,tmp,i);
		*str++;
	}
}

int
main () {
	char *str="Asdddddddddddddd";
	test(str);
	getch();
	return 0;
};
Эммм... Ну а здесь чиво? Нихрена не андестэнд (
 

fixxxer

К.О.
Партнер клуба
char tmp;
printf("%s %s %i\n",str,tmp,i);

обращение к адресу в диапазоне 0...255 это вряд ли то, чего ты хотел :)
 

cDLEON

Онанист РНРСlub
Pigmeich
Гыгы....Йа хател увеличить указатель на единичку.
Что бы на следующую итерацию указатель указывал уже на следующий символ.
В этом месте всё норм. 100%. Убираю tmp=*str; Всё работает как нужно. А вот присвоить текущий в итерации символ не получается. Потому как на операции присваивания моя программко и обваливается)
fixxxer
Стоп...Не понил) Если можно по-проще говори)) Я на этот СИ как баран на новые ворота смотрю))

-~{}~ 18.12.07 08:57:

Стоп. А почему увеличиваем не указатель на 1, а хз чо ?
И что в таком случае такое str ?
Я просто не могу до конца в логику этих указателей въехать...
Поэтому и мудрю)
 

fixxxer

К.О.
Партнер клуба
вообще надо просто понять.
указатель - это просто число. самое обычное. адрес в памяти.
на это указывает * в объявлении
"разыменование" = "взять значение, которое лежит по этому адресу"
тип (char * /int */ etc) указывает грубо говоря только на то сколько последовательных байт мы берем при разыменовании.
у самого указателя тоже есть адрес в памяти (где то же должен этот самый адрес храниться) - по сути это обычное целочисленное значение, а специальные обозначения нужны только чтобы ты не запутался и компилятор мог это проверить.

вот у тебя есть char tmp
это значит что где-то выделена ячейка размером в sizeof char (1 байт), у нее есть какой-то адрес - а именно &tmp

(disclaimer: я специально упрощаю, умникам не докапываться ;)).

далее, что такое "строка". в си такого понятия вобщемто нет, ибо строка это слишком высокоуровневая абстракция:) строковые функции работают с указателями типа char*, куда они указывают в памяти - там и начало строки (где угодно собственно), условным концом строки является символ с кодом 0.

короче возьми нормальную книжку и почитай. конкретно вряд ли что посоветую, то что я читал 10 лет назад ты все равно не найдешь - разве что всякая литература по ms vc++ тебе вряд ли подойдет. ну k&r хотя бы почитай, его полно в сети
 

cDLEON

Онанист РНРСlub
fixxxer
Ну то, что ты пишешь я примерно представляю себе...
Мне интересен сам факт замечания...Ведь по-сути мне и нужен только один символ из строки в ТМП )
 

fixxxer

К.О.
Партнер клуба
да, забыл еще момент тебе наверное неочевидный

char это число. от 0 до 255
char c = 'A'
и char c = 65
это то же самое.

соответственно когда ты пишешь теперь
printf("%s", c)

что такое %s - это значит что аргумент у нас строка. то есть указатель, char *
то есть то, что начинается в памяти по адресу 65 :)

посмотри в мануале на printf, как задать вывод char.
 

cDLEON

Онанист РНРСlub
fixxxer
То, что символ - это число я вкурсе )
Ну а почему это не то, чего я хотел ? )
 

cDLEON

Онанист РНРСlub
что такое %s - это значит что аргумент у нас строка. то есть указатель, char *
Во. Теперь понятно)
посмотри в мануале на printf, как задать вывод char.
Хороший совет...Только где бы найти мануал в стиле ПХПшного...Перерыл весь поисковик. Сплошной хлам.
Даже толковых примеров по работе с памятью и указателями нет... =)

-~{}~ 18.12.07 09:19:

Логичным было, что char выводится через %c =))
Урря! Фсйо пашеД) Йа зверь =))
 

fixxxer

К.О.
Партнер клуба
у меня man 3 printf, а в твоих windows есть MSDN и все такое :)

-~{}~ 18.12.07 09:35:

ваще вот тебе 2 классические задачки

везде использовать только указатели

сделаешь - считай разобрался

1.
PHP:
#include <stdio.h>
int main(int argc, char **argv) 
{
...
}
вывести первые буквы входных параметров (пример: ./a.out this is a test должно вывести tiat)

2.
PHP:
#include <stdio.h>
#include <assert.h>
int main(int argc, char **argv)
{
   assert(2==argc);
   printf("%s\n",str_reverse(argv[1]));
   return 0;
}
реализовать ф-ю str_reverse которая переворачивает строку на месте (не выделяя доп. память).
 
Сверху