Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> разъименовывание неинициализированных указателей 
:(
    Опции темы
GQU
Дата 29.8.2014, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 13.2.2011

Репутация: нет
Всего: нет



Почему в одном случае ошибка, а в другом нормально?

Ошибка
Код

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int* p;
    int a;
    int b = 44;
//  int c = 25;
    printf("*p = %d  \n",*p);
    return 0;
}

а тут норм
Код

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int* p;
    int a;
    int b = 44;
    int c = 25;
    printf("*p = %d  \n",*p);
    return 0;
}



Это сообщение отредактировал(а) GQU - 29.8.2014, 20:29
PM MAIL   Вверх
Romikgy
Дата 29.8.2014, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 1
Всего: 146



и там и там должна быть ошибка , обращение к неинициализированой переменой (в воздух) , попало в сегмент программы ошибки нет , попало за него вывалится с ошибкой


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
GQU
Дата 29.8.2014, 20:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 13.2.2011

Репутация: нет
Всего: нет



Цитата

обращение к неинициализированой переменой (в воздух) 

в указатель также как в переменную если не инициализировать попадает какое то значение не больше int, и это значение он выводит

Странно, а почему в первом случае  p всегда одинакова(у меня всегда 64), а во втором всегда разная

//тут p  всегда одинакова
Код

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int* p;
    int a;
    int b = 44;
//  int c = 25;
    printf("p = %d  \n",p);
    return 0;
}


//тут p  всегда разная
Код

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int* p;
    int a;
    int b = 44;
    int c = 25;
    printf("p = %d  \n",p);
    return 0;
}


Это сообщение отредактировал(а) GQU - 29.8.2014, 21:02
PM MAIL   Вверх
Romikgy
Дата 29.8.2014, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 1
Всего: 146



Цитата(GQU @  29.8.2014,  19:47 Найти цитируемый пост)
в указатель также как в переменную если не инициализировать попадает какое то значение не больше int, и это значение он выводит

указатель это адрес! вот в указатель попадает случайное число ... это получается случайный адрес, и из этого адреса вы пытаетесь что то прочитать... если этот случайный адрес в вашем адресном пространстве ошибки не будет , если за ним, будет ошибка.... инициализация неинициализированой переменой происходит остатками процесса инициализации других переменных.... 
PS если очень интересно почему так происходит, отдизасемблируйте эксешник и посмотрите что происходит!

Это сообщение отредактировал(а) Romikgy - 29.8.2014, 22:13


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
GQU
Дата 29.8.2014, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 13.2.2011

Репутация: нет
Всего: нет



Цитата

инициализация неинициализированой переменой происходит остатками процесса инициализации других переменных

т.е сначала явная инициализация, потом что осталось на неинициализированные переменные?
PM MAIL   Вверх
feodorv
Дата 29.8.2014, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(GQU @  29.8.2014,  21:47 Найти цитируемый пост)
в указатель также как в переменную если не инициализировать попадает какое то значение не больше int, и это значение он выводит

Гм. Указатель - тоже переменная, и именно значение этой переменной будет случайно-мусорным, "если не инициализировать". Грубо говоря, значение указателя - это номер байта в адресном пространстве процесса, на который он указывает (отчего он и "указатель"). Если это указатель на int (как в Вашем случае), то он указывает сразу на четыре последовательных байта, начиная именно с того номера байта, которое есть значение указателя. Только в этом смысле неинициализированный обладает значением.

Ну а та область памяти, на которую указывает указатель, может быть элементарно недоступна на чтение/запись. То есть не все адресное пространство процесса доступно хотя бы для чтения, не говоря уже о записи. В своей программе Вы можете написать такой код:
Код
int *p = (int *) 0;
printf( "*p = %x\n", *p);
и сколько угодно удивляться тому, чего это программа падает, ведь с точки зрения компилятора всё написано правильно. Но увы, помимо языка программирования нужно знать особенности ОС. А обычно ОС устроена так, что не все адреса в процессе доступны для работы с ними.

Поэтому Ваш неинициализированный указатель (хотя он и имеет какое-то мусорное значение и указывает куда-то внутрь адресного пространства процесса) может указывать куда у годно, как в доступную на чтение область памяти, так и в не доступную. В первом случае печать значения по "мусорному" адресу выводит какое-то "мусорное" же значение, во втором случае - программа падает. Никаких чудес.

Цитата(GQU @  29.8.2014,  21:47 Найти цитируемый пост)
тут p  всегда одинакова

Цитата(GQU @  29.8.2014,  21:47 Найти цитируемый пост)
тут p  всегда разная

Вы сейчас копаетесь в мусоре. Как там карты лягут, как инициализируется процесс, какие там получаюется значения неинициализированного указателя, какие там значения лежат в памяти по этим адресам - предсказать не возможно. Сегодня у Вас p всегда одинакова, потом вдруг разная... Мусор есть мусор.



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GQU
Дата 29.8.2014, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 13.2.2011

Репутация: нет
Всего: нет



Цитата

Грубо говоря, значение указателя - это номер байта в адресном пространстве процесса

это не номер, это значение какого то случайного байта

PM MAIL   Вверх
Merlin_ua
Дата 29.8.2014, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 22.11.2006

Репутация: нет
Всего: нет



Цитата(GQU @ 29.8.2014,  22:51)
Цитата

Грубо говоря, значение указателя - это номер байта в адресном пространстве процесса

это не номер, это значение какого то случайного байта

это не значение какого то случайного байта . это адрес, гре рассположен объект. 
PM MAIL   Вверх
GQU
Дата 29.8.2014, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 13.2.2011

Репутация: нет
Всего: нет



Цитата

это не значение какого то случайного байта . это адрес, гре рассположен объект

смотря с какой стороны смотреть
если так
Код

int a = 5;
int* p = &a;

то p это адрес, по которому располагается a

А если принимать указатель за переменную, то если ее не инициализировать, в ее 4 байта попадает случайный мусор, так же как и в любую другую неинициализированную переменную, например int
Просто в случае указателя эти данные будут восприниматься как адрес, а в случае int, как целое число

Это сообщение отредактировал(а) GQU - 29.8.2014, 23:08
PM MAIL   Вверх
feodorv
Дата 30.8.2014, 01:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Уважаемый GQU, указатель - это всего лишь беззнаковое целочисленное значение, специальным образом интерпретируемое (то есть для него возможна операция разименовывания). В своих рассуждениях Вы смешиваете значение указателя (то самое число) и область памяти, на которую он указывает. Это две разные (пусть и связанные) вещи. В Вашей фразе
Цитата(GQU @  29.8.2014,  23:51 Найти цитируемый пост)
это не номер, это значение какого то случайного байта

Вы уже предполагаете, что указатель разименовывается, а это не верно. Указатель автоматически не разименовывается никогда. Для разименовывания указателя нужно применить специальную операцию (звездочку).



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Merlin_ua
Дата 30.8.2014, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 22.11.2006

Репутация: нет
Всего: нет



Цитата

смотря с какой стороны смотреть

Да как не посмотри.
Цитата

А если принимать указатель за переменную

Это как? Конечно, над указателями применима арифметика, что и над переменными, но указатель - это указатель, переменная - это переменная. И если уже сравнивать указатель на int с int, то это неудачное сравнение. Память не может располагаться по отрицательному адресу.  Здесь уместно будет сравнение с unsigned int. Вы, похоже, путаете значение указателя с значением объекта, на который ссылается указатель
PM MAIL   Вверх
Merlin_ua
Дата 30.8.2014, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 22.11.2006

Репутация: нет
Всего: нет



Да, вот еще, Ваши оба примера у меня вывалились с ошибкой (С++). В конфигурации release оба отработали без ошибок. 
PM MAIL   Вверх
GQU
Дата 31.8.2014, 07:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 13.2.2011

Репутация: нет
Всего: нет



Цитата

это не номер, это значение какого то случайного байта

неправильно сказал
это значение каких то 4-х случайных байт
Цитата

Вы уже предполагаете, что указатель разименовывается, а это не верно

я предполагаю, что 4 случайных байта это адрес, а если мы пишем *указатель, то это уже данные, на которые указывают эти 4 случайных байта
Цитата

Да, вот еще, Ваши оба примера у меня вывалились с ошибкой (С++)

так нет инициализации, на разных компиляторах по разному, если который в ВизуалСтудио, там среда сама генерирует исключение, а на gcc норм
Цитата

А если принимать указатель за переменную
Это как?

А указатель это и есть переменная, прсто в ней содержится адрес
Цитата

Конечно, над указателями применима арифметика, что и над переменными, но указатель - это указатель, переменная - это переменная.
 
Неправильно
Цитата

И если уже сравнивать указатель на int с int, то это неудачное сравнение

я сравнивал не с int, а с 4-мя байтами, подразумевал беззнаковое целое

Это сообщение отредактировал(а) GQU - 31.8.2014, 07:25
PM MAIL   Вверх
baldman88
Дата 31.8.2014, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 1
Всего: 7



Цитата(GQU @  31.8.2014,  07:15 Найти цитируемый пост)
я предполагаю, что 4 случайных байта это адрес, а если мы пишем *указатель, то это уже данные, на которые указывают эти 4 случайных байта

Указатель всегда указывает на начальный байт адреса, где лежат данные. Компилятор уже сам, исходя из типа указателя, опрделяет из скольких байт, следующих за начальным адресом, взять данные.
Попробуйте сделать так:
Код

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    int* ip;
    double* dp;
    printf("ip = %u; ip++ = %u\n", ip, ip++);
    printf("dp = %u; dp++ = %u\n", dp, dp++);
    return 0;
}
Здесь компилятор сам вычисляет на сколько нужно сдвинуть указатель для каждого из типов. Так что указатель -- беззнаковое число, в котором хранится начальный адрес на область данных. Разыменовывание (операция *) говорит компилятору: сходи по такому-то адресу и возьми столько-то байт (в зависимости от типа на который указывает этот самый указатель).
И да, все указатели имеют одинаковую длину в байтах (в пределах данной архитектуры ОС), независимо от типа данных, на который они указывают. Если не прав -- поправьте, но мне это видится именно так.
PM MAIL   Вверх
feodorv
Дата 31.8.2014, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(baldman88 @  31.8.2014,  15:01 Найти цитируемый пост)
    printf("ip = %u; ip++ = %u\n", ip, ip++);
    printf("dp = %u; dp++ = %u\n", dp, dp++);

Я бы все же использовал %p.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0619 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.