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

cDLEON

Онанист РНРСlub
Чистый СИ. Указатели.

Захотелось отвлечься от ПХП на денёк.
Решил опять погрызть и покурить мануалы по СИ.
Только вот ни хрена я не понимаю работу с указателями.
Вот пару примеров:
Почему char *p = "blabla"; работает, а если я начинаю делать похожие манипуляции в своей функции, у меня происходит переполнение.
Вот в мануале нарыл ещё одну непонятную хрень:
Операции над указателями не ограничиваются только операциями ++ или --. К указателям можно прибавлять некоторое целое или вычитать целое Пусть, например, величина x=2000 и указатель этого числа p указывает на целое число. Пусть первоначально значение указателя p=1245064 в десятичной системе счисления. Тогда в результате выполнения оператора p=p+5 значение указателя будет p=1245084. Действительно, это верно, поскольку целочисленная величина типа int в 32-битном представлении занимает 4 байта, отсюда p=1245064 + 4*5 = 1245084.
Чйо это значед? Неужели в каждом последующем байте по еденичке содержится?
Да и вообще не понятно. Как с этой дурацкой памятью работать. Вечно какие то переполнения и проч. Вроде бы делаю:
Код:
void
func(char *str) {
	char *str2,*str3,*str4;
	*str2=++*str;
	*str3=*(str+2);
	*str4=*str3-*str2;
	printf("%p",str4);
}

int
main () {
	char *str="Asd";
	func(str);
	getch();
};
По логике вещей, я получаю разность указателей. Это тоже указатель, значит память выделять не нужно. Но после компилирования этого кусочка кода - опять переполнения...
Извеняюсь за такие вопросы. Всё что нашёл в инете больше смешило, чем учило.
Во например...Как вам..."Числа с плавающей запятой". :D Поэтому начал эксперементировать с ними сам....
 

nerezus

Вселенский отказник
Переполнение? Тут имхо ошибка сегментации(есть обращение к непонятным адресам и изменение их значений).

Ошибки во 2,3,4 строках 1ой ф-ии. Нету return в ф-ии типа int - это вообще ошибка синтаксиса.

P.S. выучил бы хоть основы синтаксиса для начала.

Код:
#include <stdio.h>

void func(char *str) {
    char *str2,*str3;
    int str4;
    str2 = ++str;
    str3 = str + 2;
    str4 = str3 - str2;
    printf("%d",str4);
}

int main () {
    char * str = "Asd";
    func(str);
    return 0;
};
 

cDLEON

Онанист РНРСlub
nerezus
Ну синтаксис я знаю. Компилятор не матюкается - и хорошо...
ЗЫ. Я не знаю,что это за ошибка. У меня компилятор молчит.
А запускаю откампиленную прогу, вылетает DWWIN и спрашивает отправлять отчёт либо не нужно. Вод.
Кстати...Попутно вопрос...Нужно ставить какой-то другой софт для отладки программ ?
Где здесь неизвестный адрес?

-~{}~ 17.12.07 07:56:

Да вообще то я хотел написать что то вроде ПХПшной substr =))
 

nerezus

Вселенский отказник
Ну синтаксис я знаю. Компилятор не матюкается - и хорошо...
Если ты не видишь ошибки, это не значит. что ее нету. Особенно в случае, когда она точно есть.

Нужно ставить какой-то другой софт для отладки программ ?
Я не использую дополнительного софта.

Где здесь неизвестный адрес?
*str2=++*str;

Ты записываешь значение по адресу str2. На что показывает str2 мы не знаем. Ошибка.

Да вообще то я хотел написать что то вроде ПХПшной substr =))
Тогда советую посмотреть, что делает эта ф-ия. И сравнить с тем, что делаешь ты.
P.S. тебе необходима ф-ия malloc будет для выделения памяти.
 

cDLEON

Онанист РНРСlub
КаГ это не знаем ? )
Код:
void
func(char *str) {
	char *str2,*str3,*str4;
	*str++;
	//*str3=*(str+2);
	//*str4=*str-*str3-*str2;
	printf("%s",str);
}

int
main () {
	char *str="Asd";
	func(str);
	getch();
	return 0;
};
Вот этот принтф выводит sd
Хотелось бы, что бы ф-я возвращала указатель на промежуток в памяти =))) Ведь, в большинстве случаев мне модифицировать ничйо не нужно будет потом )
 

Pigmeich

Новичок
cDLEON
А-а, я прибежал раньше Александра.

*str2=++*str;
*str3=*(str+2);
*str4=*str3-*str2;
Шурик, ты балбес. Есть указатель, который есть суть адрес памяти, а есть его разыменованиое значение.

*str - это 'A'. Потому что char* - это укзатель на символ и никаких массивов. А строка в C - это то куда указывает указатель продленное до нулевого символа.

++ *str == 'B'. Серьезно.

Указатели можно прибавлять и отнимать, так они адреса памяти, суть целые. Но разыменовывать их перед этим не надо.

-~{}~ 17.12.07 11:59:

kruglov
у него void-функция. В них return можно не писать.

-~{}~ 17.12.07 12:02:

cDLEON
Означает это следующее:
1. Вытащить значение указателя.
2. Сохранить.
3. Прибавить еденицу к тому что хранилось (может и после выражение выполниться, в любом случае влияет только после строчки).
4. Разыменовать.
5. Выбросить разыменованое значение.

Я тут калякал экономные строки на range-ах, показать? Только там сплошные шаблоны.
 

cDLEON

Онанист РНРСlub
Такс...
Значед, присваивая указателю значение другого указателя, мы получаем совсем другой кусок памяти? Т.е. по-сути создаётся ещё одна переменная?
Всё таки всё равно для меня тёмный лес все эти указатели 8)
Если б начал писать все вопросы, которые у меня возникли, получилось бы пару страниц =))
ЗЫ. Как в эклипсе сделать подсветку атрибутов для ф-й ? А то чйот не подствечиваюццо =(

-~{}~ 17.12.07 12:11:

О. Ты меня опередил)
Покажи, буду очень признателен =)) А то с операциями над строками тоже не всё ясно)
 

ys

отодвинутый новичок
cDLEON

>Значед, присваивая указателю значение другого указателя, мы получаем совсем другой кусок памяти? Т.е. по-сути создаётся ещё одна переменная?

Нет, это участок памяти, на который указывал первый указатель, становиться более нам не известен.

Еще есть такие вкусности, как "указатель на указатель", точнее - ссылка на указатель :).
 

ys

отодвинутый новичок
cDLEON


Мне, обычно такой пример мозги просушивает: :)

Код:
int foo(char **out, char *in) {

    if (!*out)
       return -1;

    free(*out);
    *out = NULL;

    *out = strdup(in);     
   return 0;
}
-~{}~ 17.12.07 12:30:

Pigmeich

*str++;
>Означает это следующее:
....
Хм, странно. А у меня вот такой код работает и не жужжит.
Судя по Вашему описанию, он работать не должен.

Код:
/* find key */
i = 0;
while (*c && *c != '=' && *c != ',' && !isspace(*c) )
    key[i++] = *c++;
key[i] = '\0';
(Код взят из исходников apache)
 

Alexandre

PHPПенсионер
Да вообще то я хотел написать что то вроде ПХПшной substr =))
есть уже готовая функция substr()
используй готовые функции или решения: http://forums.devx.com/archive/index.php/t-87666.html.

-~{}~ 17.12.07 12:40:

Мне, обычно такой пример мозги просушивает:
нормальный сишный код :)

-~{}~ 17.12.07 12:45:

func(char *str) {
char *str2,*str3,*str4;
*str2=++*str;
*str3=*(str+2);
*str4=*str3-*str2;
printf("%p",str4);
}
*str4=*str3-*str2; - вот на этой строке очевидно и вылетает....так как берется знапчение по адресу, являющимся разностью указателей str3 и str2, а там граница памяти за пределами программы... или вообще Ось в целом.

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

zerkms

TDD infected
Команда форума
*str3=*(str+2); - указателю str3 присваивается значение указателя на str2( плюс 2 к значению - непонятно зачем , т.е. если был символ '1', то станет символ '3', a -> c, А -> Г etc... )
вообще-то разыменование происходит после вычисления адреса. адрес приращается на 2 (1 == sizeof(str))
 

zerkms

TDD infected
Команда форума
*str4=*str3-*str2; - вот на этой строке очевидно и вылетает....так как берется знапчение по адресу, являющимся разностью указателей str3 и str2, а там граница памяти за пределами программы... или вообще Ось в целом.
тут в область памяти по адресу str4 происходит запись значения, равного разнице значений по адресам str3 и str2 соответственно.
 

cDLEON

Онанист РНРСlub
Не..Я проверял ) Падает на самой первой операции присваивания )
str2=++*str;
 

Pigmeich

Новичок
ys
Хм, странно. А у меня вот такой код работает и не жужжит.
Судя по Вашему описанию, он работать не должен.
Судя по-моему описанию, я ничего не говорил будет он работать или нет. :)
Работать будет.
 
Сверху