![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
alexvs11 |
|
|||
hell is here ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 21.8.2010 Репутация: 2 Всего: 10 |
Сыроежка, приведите выдержку из стандарта про выравнивание, раз вы его тут упоминали
|
|||
|
||||
Сыроежка |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 127 Регистрация: 24.6.2011 Репутация: 1 Всего: 1 |
||||
|
||||
volatile |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
а такой код будет корректным ? ![]()
Еесли Нет, приведите пример машины, операционной системы, да хоть чего-нибудь, где этот код работать не будет. (именно этот код с for) Если Да, то как может в целом корректный код состоять из нескольких некорректных операций? |
||||||
|
|||||||
hawk3500 |
|
||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 246 Регистрация: 6.2.2009 Репутация: нет Всего: 2 |
Сыроежка вот вы говорили:
Изначально вопрос стоял так:
Игнорировать арифметику указателей-означает прежде всего не привязываться к базовым типам. Если у меня есть указатель на тот или иной участок памяти и задача сдвинуть на несколько байт, то я просто прибавлю к к имеющемуся значению в указателе значение равное сумме того что есть + 3. А вот какой тип данных вы будете использовать мне всё равно. С точки зрения программы адресное пространство масива линейно и применение понятия выравнивания не корректно, разве что быть может это учитываеться в каких нибудь древних системах или при низкоуровневом программировании...но мы о нём речи не ведём. Пришлите скрин отладчика(ОС значения не имеет) под которым мя явно увидим что это приведёт к падению системы..... Это сообщение отредактировал(а) hawk3500 - 26.6.2011, 23:31 --------------------
воин dzen'a |
||||
|
|||||
volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
hawk3500, на некоторых платформах (микроконтроллеры напр.) действительно нельзя обращаться по указателям не выровненным на слово. К PC (Personal Computer), да и вообще к любым машинам на X86 это не отностися, не важно какая система (win*; dos*; *nix).
Сделаю ударение нельзя именно обращаться. Но здесь никто и не обращается Мы только прибавляем число к указателю. ![]() Это сообщение отредактировал(а) volatile - 27.6.2011, 00:06 |
|||
|
||||
volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
удалил. не к чему это.
Это сообщение отредактировал(а) volatile - 27.6.2011, 01:54 |
|||
|
||||
borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 21 Всего: 135 |
>на некоторых платформах (микроконтроллеры напр .) действительно нельзя обращаться по указателям не выровненным на
слово Мало того, на некоторых компиляторах размер char равен размеру short и равен размеру int - AnalogDevice под какой-то свой процессор (161-й по-моему) -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
Hagrael |
|
||||||||||||||||||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 143 Регистрация: 26.6.2011 Репутация: нет Всего: нет |
Спасибо всем, кто мне ответил!
Данный код некорректен из-за того, что оператор + может связывать переменную типа type* (любой указатель) только с переменной типа int.
А почему некорректен этот код, мне непонятно. Однако, думаю, что прежде следует понять, почему не работает код, приведенный ниже:
Консоль абсолютно чиста, если не считать статуса завершения программы. Из-за чего?
Массив на самом деле ведь указывает на свою первую ячейку. Однако это не просто указатель, а константа-указатель. Следующий код приводит к ошибке " non-lvalue in assignment ":
А следующий - к ошибке " incompatible types in assignment of `int' to `int[10]' ":
Однако я заметил, что обычные константы нельзя копировать в др. переменные без префикса constant, однако массив можно. Т. е. следующий код будет корректным:
А следующий - нет, т. к. нет префикса const перед второй строкой:
Так что же это такое - массив? Это не просто const type* ![]()
Вот что я понял. К переменным всех типов присваиваются их литералы, которые заранее никуда в ОЗУ не копируются. Единственное - исключение может составить указатель, указывающий на строку. Тогда строковый литерал изначально превращается в массив типа char, и когда дело доходит до инициализации нашего указателя, то в него возвращается заранее созданный массив. А под локальные переменные неиспользуемой функции выделяется место? Или оно выделяется под них только при запуске функции? А где хранятся все те литералы, которые посылаются в аргументы? В памяти той функции, из которой вызывается другая функция, принимающая литералы в качестве аргументов? И еще вопрос: .exe-файл на протяжении всей программы хранится в ОЗУ. Но зачем? Разве из него сразу же не вытянули всю информацию? Мне все говорят, что указатель - это переменная, хранящая адрес. Но ведь компьютер не видит этой разницы, так?
Если ты ввел в первый раз менее 4-х символов, то компьютер тебя просит ввести еще одну строку, после чего выводится то, что ты ввел в первый раз и то, что ты ввел во второй раз. Однако если ты введешь 4 символа или более, то тебе не предоставится второй возможности ввести строку, вместо этого на экран выведутся 3 первых буквы из того, что ты ввел в этот единственный раз и на пустота, находящаяся строчкой ниже. Можете объяснить это поведение? Кстати, касательно функции cin.getline: она странно работает - возвращает 3 символа, когда я вторым аргументом послал число 4! Что это такое? И новый вопрос: 7) Что такое "конец слова" и "выравнивание под конец слова"? Заранее благодарю. Это сообщение отредактировал(а) Hagrael - 27.6.2011, 10:21 |
||||||||||||||||||||||
|
|||||||||||||||||||||||
bsa |
|
||||||||||||||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Здесь и далее у тебя уже начинается путаница. "константный указатель" и "указатель на константу" в большинстве случаев значит одно и тоже (хотя, должно значить разное): const type * pointer "указатель-константа" - это уже несколько другое: type * const pointer Разница в следующем: в первом случае ты имеешь право менять УКАЗАТЕЛЬ (например, чтобы он указывал в другое место), но не имеешь права менять элемент, на который он указывает, а во втором ты имеешь право менять элемент, но не сам указатель. Разницу видишь? Массив имеет свой собственный тип - массив (type[n]). Его можно воспринимать, как "указатель-константа". Но в отличие от последнего, sizeof() возвращает не размер указателя, а занимаемое место (в char'ах) массивом.
в коде программы (когда надо вызвать твою функцию, процессор получает команды: запихать 10 в стек, запихать 50 в стек, вызвать подпрограмму по адресу такому-то, ..., откатить стек на <размер аргументов>).
Еще раз рекомендую почитать ответы на часто задаваемые вопросы (тема прикреплена). http://cplusplus.com/reference/iostream/istream/getline/ почитай, когда включается failbit. Кстати, после возникновения ошибки и до ее снятия читать не получится. под "словом" понимается так называемое "машинное слово". Т.е. это данные такого размера, работа с которыми для процессора наименее трудоемка. Наиболее популярны 32 и 64 бита (4 и 8 байт, соответственно). У современных процессоров все узлы оптимизированы на работу с такими словами. Но платой за это является снижение производительности при невыравненном доступе: представь, процессор за 1 такт читает 4 байта с адресов, кратных 4. Чтобы прочитать данные, которые лежат только кратно 2, ему придется прочитать 2 раза по 4 байта, а затем лишние байты выкинуть. А теперь представь, что нужно сделать, чтобы записать: прочитать 4 байта, заменить 2 на новые данные, записать, прочитать еще 4 байта, заменить 2 байта на новые, записать.... Минимум 4 такта вместо 1. Именно поэтому все современные компиляторы умеют делать выравнивание по границе машинного слова. |
||||||||||||||||||||
|
|||||||||||||||||||||
Hagrael |
|
||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 143 Регистрация: 26.6.2011 Репутация: нет Всего: нет |
Спасибо за ответ.
На самом деле код был таким:
Я написал 1/4 для ясности, забыв о том, что если делить один int на другой, то выполнится целочисленное деление ![]()
Т. е. технически этот код правилен, однако вы бы подумали, что его автор не знает, что делает, да?
И правда, я просто не заметил переноса строки. Немного об Endian-ах в Википедии и не до конца понял ![]() Спасибо, понял. Ах вот оно что, значит, массив - это не просто указатель на свою первую ячейку. Он не является константой (т. к. при операции int* p=int_arr; в левой стороне не нужно слово const), однако его нельзя менять. Так? Это понятно, но разве при запуске программы глобальные переменные все функции с их инструкциями не вытаскиваются? Значит, в ОЗУ все стремиться к подобному порядку: 4 байта | 8 байт | 8 байт | ... Но зачем 2 раза читать по 4 байта, а затем лишние байты выкинуть? Вы говорите о таких размерах, как 5-7 байт? Тогда, выходит, это устроено так: 1. Нашел адрес; 2. Считал 8 байт (2 раза по 4 байта); 3. Выкинул 2 байта (т. к. нужно было только 6 байт) А по 8 процессор читать не может, да? Я английский знаю не ахти, но я так понял, дело в том, что failbit - это бит, перед которым получение информации прекращается. Я правильно говорю? Это сообщение отредактировал(а) Hagrael - 27.6.2011, 12:42 |
||||||
|
|||||||
bsa |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
да endianess отвечает лишь за порядок байт в ОЗУ. АЛУ работает независимо. Я же объяснил, чем "указатель на константу" отличается от "указателя-константы". const int *p - указатель на константу. int * const p - указатель-константа. Так вот, массив можно воспринимать как указатель-константу (хотя, на самом деле, делать так не стоит).
может. все зависит от архитектуры процессора и контроллера памяти.
failbit устанавливается при ряде ошибок чтения. В частности, getline устанавливает его, когда размер буфера меньше, чем данных в потоке. Для снятия этого бита нужно использовать метод clear(). |
||||||
|
|||||||
volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
согласен на 200%. Удивительно как точно сформулирована мысль. ![]() именно это я и хотел сказать вчера. |
|||
|
||||
Hagrael |
|
||||||||||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 143 Регистрация: 26.6.2011 Репутация: нет Всего: нет |
Простите, что так долго не понимаю...
Вот именно, как я понимаю, на самом деле, это не указатель-константа! Взять даже ошибки, которые высвечиваются в логе после этого кода:
Вот, собственно, ошибки:
Значит, массив-таки имеет свой собственный тип, схожий с указателем. Но почему его, как указатель нельзя переназначить, мне до сих пор, непонятно.
А вы можете сказать примерно, из чего состоит .exe и каким образом с его помощью работает программа (или сказать, что почитать по этому поводу). Я так понимаю, что .exe-файл содержит в себе сборник инструкций, выполняющихся одна за другой. Вот, к примеру, у меня такой код:
После компиляции, насколько я понимаю, в .exe-файле будут следующие инструкции:
И, выходит, что компьютер при запуске файла проверит его расширение, увидит, что это .exe, загрузит в память и начнет следовать инструкциям. А адрес переменным задается строгий, или же при создании переменной, для нее берется свободное место, которое по адресу ближе всех др. свободных мест к нулю? А библиотечные функции пишутся на C++ или Asm? Логичнее было бы писать их на Asm, и я бы не спросил об этом, если бы не увидел директивы #include, включающей файл с расширением .h. И еще один вопрос: Если у каждой программы своя виртуальная память, то почему выдает ошибку такая конструкция:
я же изменяю свою переменную, а не переменную чужой программы. Это сообщение отредактировал(а) Hagrael - 28.6.2011, 10:38 |
||||||||||||||
|
|||||||||||||||
triclosan |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 515 Регистрация: 18.8.2006 Репутация: 2 Всего: 12 |
Прикладной программе (не по функциональности, а по типу и правам запуска) ОС указывает какой участок памяти она может занять (строго говоря это может быть где угодно в пользовательской памяти) далее мы уже имеем дело со смещениями т.е. ваши 0xB04566 и 0xB04700 могут меняться от запуска к запуску, но переход от main к func будет - "сдвинуться на 0xB04700-0xB04566".
Большинство функции на Си как раз писаны на Asm, при этом файл .h все равно присутствует - он содержит прототипы функций, но это все вообще-то зависит от реализации. Си++ые же функции (чистых функций в std::* не так уж и много) - главным образом на Си++, причем большинство - шаблонные, поэтому реализация в виде исходного кода. Это сообщение отредактировал(а) triclosan - 28.6.2011, 12:39 |
||||
|
|||||
Сыроежка |
|
||||||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 127 Регистрация: 24.6.2011 Репутация: 1 Всего: 1 |
Вы заблуждаетесь! Это не все равно! Языки С и С++ типизированные, и у вас не просто какой-то указатель неизвестного типа, а указатель производного типа от int. Именно для вашего примера в мтандарте сказано, что такое поведение неопределенное. То есть вы можете использовать любые некорректные конструкции, но это к сущности языка не имеет никакого отношения. Теперь приведу выдержку из стандарта по языку С: "6.5.3.2 Address and indirection operators #4 If an invalid value has been assigned to the pointer the behavior of the using * operator is undefined" В комментарии к этому параграфу дается разъяснение, что означает "invalid value" "Among the invalid values for dereferencing a pointer by the using * operator are a null pointer, an address inoppropriatedly aligned for the type of object pointed to, ..." Но и это еще не все. В параграфе 6,3.2.3 №7 сказано: "A pointer of an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed to type, the behavior is undefined" очему возникли такие требования? Дело в том, что на многих млатформах типы данных должны быть соответственно выравнены. Если они не выравнены машинная операция с этими данными приводит к аварийному завершению. Добавлено через 5 минут и 52 секунды
Я вам уже объяснил! Вы очевидно с первого раза не поняли! Что вы собираетесь менять?!!! Назовите мне ту ячейку памяти, которую вы собираетесь изменить! С именем массива не связана никакая ячейка памяти! То есть нет такой ячейки, где хранится адрес массива, и которую вы могли бы изменить! В памяти хранится сам массив, то есть его элементы. А имя массива - это, можно так сказать, виртуальный адрес массива, то есть нигде этот адрес не хранится! Если бы он где-то хранился, то тогда бы вы его могли изменить. Но в этом случае это уже был бы не сам массив, а указатель на массив, то есть отдельная ячейка памяти, которую вы могли бы менять! Добавлено через 9 минут и 19 секунд
123 - это не переменная! Это константа препроцессора, которая в результате компиляции заносится непосредственно в машинную команду, которая инициализирует некоторую переменную. В приведенном ваше примере компилятор никуда не помещает 123, поэтому у этой константы нет адреса! Я вам уже все об этом в своем первом сообщении сказал. Кстати сказать это было единственное грамотное сообщение в ответ на ваш исходный вопрос, а вы его, непонятно почему, проигнорировали! Добавлено через 11 минут и 52 секунды
Я уже привел цитаты из стандарта С в своем сообщении выше, так что можете ознакомиться, почему этот код некорректный. |
||||||||||
|
|||||||||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |