реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> указатели, присвоение значений
Метценгерштейн
сообщение Nov 12 2014, 09:44
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



объявил указатель и хочу в него записать число, но ругается при компиляции. Почему я не могу в переменную сразу записать значение?
Код
uint32_t *p;
p = 0x40023800 + 0x1C;


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

Go to the top of the page
 
+Quote Post
andrew_b
сообщение Nov 12 2014, 09:47
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



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


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

Потому что так устроена адресная арифметика.
Во первых, 0x40023800 и0x1C это просто числа. Откуда видно, что это указатели? Да даже если это и были указатели, то неизвестно, объект какого размера расположен по адресу 0x40023800 или по адресу 0x1C.
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Nov 12 2014, 09:53
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



вероятно, я не так понимаю как в Си все работает.
по моему мнению, я объявил переменную- указатель.

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

здесь же я не привожу число 45 к типу int?
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Nov 12 2014, 09:53
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



вероятно, я не так понимаю как в Си все работает.
по моему мнению, я объявил переменную- указатель.

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

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

здесь же я не привожу число 45 к типу int?
Go to the top of the page
 
+Quote Post
megajohn
сообщение Nov 12 2014, 10:07
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(Метценгерштейн @ Nov 12 2014, 12:44) *
Код
uint32_t *p;
p = (uint32_t  *)0x40023800 + 0x1C;


кстати, это будет эквивалентно p = (uint32_t *)0x40023800 + (sizeof(uint32_t))*0x1C = 0x40023870 а не 0x4002381С


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
ViKo
сообщение Nov 12 2014, 10:44
Сообщение #6


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Метценгерштейн @ Nov 12 2014, 12:44) *
объявил указатель и хочу в него записать число, но ругается при компиляции. Почему я не могу в переменную сразу записать значение?

Мало объявить указатель, надо, чтобы он куда-то указывал.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 12 2014, 10:52
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Метценгерштейн @ Nov 12 2014, 11:53) *
здесь же я не привожу число 45 к типу int?
Хм... Дело в том, что константа 45 уже имеет тип int. И число 0x40023800 тоже имеет тип int. Поэтому его нельзя просто взять и присвоить указателю, нужно явное приведение типа. Как нельзя присвоить целое число структуре или массиву.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
V_G
сообщение Nov 12 2014, 11:24
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



2Метценгерштейн
В понятие указателя входит не просто одно число (адрес), но и длина переменной, на которую он указывает. Поэтому инкрементирование указателя (увеличение на 1) приводит в вашем случае (uint32) к увеличению адреса на 4, если адресуется байтовая память, или на 2, если память процессора состоит из 16-битных слов, или на 1 для 32-разрядных процессоров.
Потому компилятору и надо сообщить тип адресуемой переменной.
Опять-таки в вашем случае в зависимости от типа данных и разрядности процессора абсолютное значение суммы адреса 0x40023800 и целого числа 0x1c может быть разным
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Nov 12 2014, 13:00
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



Цитата(Сергей Борщ @ Nov 12 2014, 13:52) *
Хм... Дело в том, что константа 45 уже имеет тип int. И число 0x40023800 тоже имеет тип int. Поэтому его нельзя просто взять и присвоить указателю, нужно явное приведение типа. Как нельзя присвоить целое число структуре или массиву.

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

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

Go to the top of the page
 
+Quote Post
V_G
сообщение Nov 12 2014, 13:14
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



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

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

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

Так что ваша логика-недоумение понятны вам (и мне): если в левой части стоит указатель на int32, то правую часть стоит автоматически привести к этому типу. Но хороший стиль программирования должен исключать двусмысленности.
В вашем же примере: p = 0x40023800 + 0x1C кто поймет, что первое число - адрес, а второе - модификатор?
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Nov 12 2014, 13:46
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



Цитата(V_G @ Nov 12 2014, 16:14) *
Еще раз, указатель по сути - это не одно число, а два (адрес и размер переменной).
Привести одно целое число 56 к целому же типу char по умолчанию вполне возможно, т.к. в обоих случаях это одно число.
Привести же одно число к двойному без явного указания на размер невозможно.

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

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


да, спасибо. Более- менее прояснилось.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 15:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.0147 секунд с 7
ELECTRONIX ©2004-2016