Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: указатели
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Метценгерштейн
объявил указатель и хочу в него записать число, но ругается при компиляции. Почему я не могу в переменную сразу записать значение?
Код
uint32_t *p;
p = 0x40023800 + 0x1C;


ругаться перестает, когда сначала приведу к типу
Код
uint32_t *p;
p = (uint32_t  *)0x40023800 + 0x1C;

andrew_b
Цитата(Метценгерштейн @ Nov 12 2014, 13:44) *
объявил указатель и хочу в него записать число, но ругается при компиляции. Почему я не могу в переменную сразу записать значение?
Код
uint32_t *p;
p = 0x40023800 + 0x1C;


ругаться перестает, когда сначала приведу к типу
Код
uint32_t *p;
p = (uint32_t  *)0x40023800 + 0x1C;

Потому что так устроена адресная арифметика.
Во первых, 0x40023800 и0x1C это просто числа. Откуда видно, что это указатели? Да даже если это и были указатели, то неизвестно, объект какого размера расположен по адресу 0x40023800 или по адресу 0x1C.
Метценгерштейн
вероятно, я не так понимаю как в Си все работает.
по моему мнению, я объявил переменную- указатель.

дальше я в нее кладу любое значение, например,
Код
int a;
a =45;

здесь же я не привожу число 45 к типу int?
Метценгерштейн
вероятно, я не так понимаю как в Си все работает.
по моему мнению, я объявил переменную- указатель.

дальше я в нее кладу любое значение.

например,
Код
int a;
a =45;

здесь же я не привожу число 45 к типу int?
megajohn
Цитата(Метценгерштейн @ Nov 12 2014, 12:44) *
Код
uint32_t *p;
p = (uint32_t  *)0x40023800 + 0x1C;


кстати, это будет эквивалентно p = (uint32_t *)0x40023800 + (sizeof(uint32_t))*0x1C = 0x40023870 а не 0x4002381С
ViKo
Цитата(Метценгерштейн @ Nov 12 2014, 12:44) *
объявил указатель и хочу в него записать число, но ругается при компиляции. Почему я не могу в переменную сразу записать значение?

Мало объявить указатель, надо, чтобы он куда-то указывал.
Сергей Борщ
Цитата(Метценгерштейн @ Nov 12 2014, 11:53) *
здесь же я не привожу число 45 к типу int?
Хм... Дело в том, что константа 45 уже имеет тип int. И число 0x40023800 тоже имеет тип int. Поэтому его нельзя просто взять и присвоить указателю, нужно явное приведение типа. Как нельзя присвоить целое число структуре или массиву.
V_G
2Метценгерштейн
В понятие указателя входит не просто одно число (адрес), но и длина переменной, на которую он указывает. Поэтому инкрементирование указателя (увеличение на 1) приводит в вашем случае (uint32) к увеличению адреса на 4, если адресуется байтовая память, или на 2, если память процессора состоит из 16-битных слов, или на 1 для 32-разрядных процессоров.
Потому компилятору и надо сообщить тип адресуемой переменной.
Опять-таки в вашем случае в зависимости от типа данных и разрядности процессора абсолютное значение суммы адреса 0x40023800 и целого числа 0x1c может быть разным
Метценгерштейн
Цитата(Сергей Борщ @ Nov 12 2014, 13:52) *
Хм... Дело в том, что константа 45 уже имеет тип int. И число 0x40023800 тоже имеет тип int. Поэтому его нельзя просто взять и присвоить указателю, нужно явное приведение типа. Как нельзя присвоить целое число структуре или массиву.

если следовать этой логике, что все числа уже типа int, а раз мы присваиваем число в другой тип, то надо явно преобразовать к типу, то!
мы же может переменной char i = 56; сделать?
56 - int, мы же не приводим ее к типу char?

V_G
это я понимаю, что увеличение указателя на 1 приведет к увеличению на int след. адреса. Мы и объявили указатель р как uint32_t. Это было заранее сделано.

V_G
Цитата(Метценгерштейн @ Nov 12 2014, 23:00) *
мы же может переменной char i = 56; сделать?
56 - int, мы же не приводим ее к типу char?

Еще раз, указатель по сути - это не одно число, а два (адрес и размер переменной).
Привести одно целое число 56 к целому же типу char по умолчанию вполне возможно, т.к. в обоих случаях это одно число.
Привести же одно число к двойному без явного указания на размер невозможно.

Кстати, неявные правила приведения типов - один из недостатков Си, порождающий много багов. И поэтому, в частности, в С++ имеется более строгий контроль соответствия, хотя и там возможно char i = 56

Так что ваша логика-недоумение понятны вам (и мне): если в левой части стоит указатель на int32, то правую часть стоит автоматически привести к этому типу. Но хороший стиль программирования должен исключать двусмысленности.
В вашем же примере: p = 0x40023800 + 0x1C кто поймет, что первое число - адрес, а второе - модификатор?
Метценгерштейн
Цитата(V_G @ Nov 12 2014, 16:14) *
Еще раз, указатель по сути - это не одно число, а два (адрес и размер переменной).
Привести одно целое число 56 к целому же типу char по умолчанию вполне возможно, т.к. в обоих случаях это одно число.
Привести же одно число к двойному без явного указания на размер невозможно.

Кстати, неявные правила приведения типов - один из недостатков Си, порождающий много багов. И поэтому, в частности, в С++ имеется более строгий контроль соответствия, хотя и там возможно char i = 56

Так что ваша логика-недоумение понятны вам (и мне): если в левой части стоит указатель на int32, то правую часть стоит автоматически привести к этому типу. Но хороший стиль программирования должен исключать двусмысленности.
В вашем же примере: p = 0x40023800 + 0x1C кто поймет, что первое число - адрес, а второе - модификатор?


да, спасибо. Более- менее прояснилось.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.