Указатель на тип char (один байт). Т.е. идентификатор такого типа содержит не данные, а указатель на область памяти где эти данные находятся.
Piflit, звёздочка как раз и говорит о том, что данный идентификатор означает, что это не данные а указатель на реально место хранения данных. Пример: int *pint; int intvar = 10; На текущий момент pint не определён (содержит в себе неопределённый указатель), т.е. переменная pint которая связана с какой-то ячейкой памяти содержит в себе мусор, а переменная intval, которая связана с какой-то ячейкой памяти содержит целое число 10. pint = &intvar; Теперь pint содержит в ячейки памяти адрес по которому находятся данные из intvar; И если ты сделаешь printf("%d", *pint), то на экран выведется 10. Обрати внимание, чтобы получить значение, которое находится по указателю, нужно применить операцию разыменования (*). А вообще читай азы по сям...
Небольшое отступление к сообщению groundhog. Всегда определяйте указатели. int *pint = 0; Такие мелочи приводят к ошибкам в больших проектах, читайте книги.
> а в чем различие на практике? Различие принципиальное. У тебя есть переменная scratch. Ее значение - это какие-то байты по адресу определенному. Когда ты к ней обращаешься char scratch = getColor( 0 ); компиллер генерирует такой код, например: push 0 call getColor // вызов getColor mov byte ptr [0x00401020], eax // положить результат в байт по адресу, тут ее адрес 00401020 А предположим она у тебя char *scratch. Тогда она в 32-битной системе (проца) будет 4-байтным значением (DWORD, ULONG и тп), в ней будет хранится АДРЕС чего-то. Т.е. в принципе по*** пишешь ты char *scratch, void *scrach или int *scratch. Если указываешь звездочку - это значит там будет указатель 4-байтный. А тип - это значит на какой тип данных указывает переменная. Это надо чтоб компиллер тебе говорил об ошибках возможных. Впринципе можно взять указатель и рассматривать данные по нему как данные другого типа. Пример void *ptr = (void*)0x00401020; // указатель на 0x00401020 ((mystruct*)ptr)->field1 = 0; // рассматриваем как указатель на структуру mystruct //или: *((int*)ptr) = 0; // рассматриваем *ptr (данные по адресу ptr) как int и кладем туда int тогда сначала берется значение по адресу какому-то (значение переменной), там лежит опять адрес, и значение по этому адресу уже будет *ptr. Если тебе, скажем, надо дать возможность ф-ии модифицировать переменную переданую (а не только передать ее значение) - можно передать указатель на нее. По этому адресу будет значение и ф-ия туда сможет записать свою ***ню. Или, скажем, у тебя какая-то структуру большая в памяти должна динамически выделяться, тогда делаем mystruct *s = (mystruct*)malloc( sizeof( mystruct ) ); и у тебя в s указатель на место в памяти где отделено sizeof( mystruct ) байт под структуру. s->field1 - поле структуры. а если s хранит структуру а не указатель то s.field1. лол NiOx вроде умный чел а написал ***ню) нахер определять указатели ? че за правило неписаное такое? нихера не надо определять если явно не нужно.
Кез, ты не прав. Статическая память(секции .data, .bss) иницилизируется нулями при запуске программы. У переменных в стеке и куче гарантия такой инициализации отсутствует, поэтому нужно специально инициализировать такие переменные для нормальной работы приложения. Содержимое неинициализированной переменной неопределено, зато можно точно предсказать что будет содержаться в неинициализированной области памяти. Представь себе неинициализированною стековую переменную, в ней может оказаться куча всего, в том числе сохраненные регистры, переменные от предыдущих вызовов, и тд. Все зависит от нахождения такой переменной в стеке. Стоит лишь взять определенную область памяти под контроль и появится возможность эксплутации. Конечно программистам, которые пишут для себя калькуляторы и тд плевать на такие уязвимости, однако раньше в крупных opensource проектах можно было часто встретить такие баги, сейчас они почти не попадаются. Для наглядности приведу пример: Code: unsigned int func(char *s) { char *vuln; if(s) { vuln = malloc(1024); ... } free(vuln); return 0; } А теперь подумайте, если аргумент s будет равен нулю, то указатель vuln окажется неинициализированным до конца функции, где для него будет вызвана функция free. О результате подумайте сами.
Piflit, не совсем понял тебя. Если вызвать func(0), то функция free попытается освободить vuln, который будет содержать в себе "мусор", обычно программа просто аварийно завершится.
я тоже чето не то написал. Code: unsigned int func(char *s) { char vuln; if(s) { vuln = malloc(1024); ... } free(vuln); return 0; } это уязвимым не будет. правильно?
2Piflit если бы было так: char *vuln = NULL, то все номр. А в данном случае указатель не инициализированный. т.е это косяк в проге.
http://shellcode.ru/index.php?name=News&file=article&sid=14 Указатели вовсе не обязательно иниицализировать, но новички всеже должны представлять, что существует класс уязвимостей, связанных с неинициализацией.
У меня Borland C++ Builder 6.0 Я игрался в настройках, и теперь когда компилю прогу, то пашет она, только у меня ( Как это исправить?
z01b В настройках проекта нужно отключить статические библиотеки, чтобы код входил уже в компилируемый файл -> В частности необходимо изменить настройки линкировки (linking) убрать галку -> "use dinamic RTL" . Если не поможет то ещё поищи что можно отключить