![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
GQU |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
Почему NULL сделали как ((void *)0), а не просто 0 ??
|
|||
|
||||
feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Кстати, это довольно тонкий вопрос. NULL вместо 0 нужен лишь в одном единственном случае - при передаче нулевого указателя в функцию с переменным числом аргументов. Во всех остальных случаях NULL, определенный как ((void *)0), не нужен, его вполне может заменить простой 0. Так в чём же проблема с передачей нулевого указателя в функцию с переменным числом аргументов? Допустим, мы имеем функцию с переменным числом аргументов:
Чем же нехорош вызов этой функции в виде
В первом случае 0 трактуется как "целое число", во втором - как "указатель". Если размеры (sizeof) целого числа и указателя различаются (а в эпоху 16-битных процессоров это было повальной практикой), то в стек вызова func поступает разное количество байт: в случае "0" - 2 нулевых байта, в случае "(void *) 0" - честных 4 нулевых байта для 16-битной системы. И получается, что в первом случае в стек не докладывается 2 нужных нулевых байта, которые func всё равно изымает из стека, но которые будут мусорными и содержать с огромной вероятностью отнюдь не нули, что приведет к появлению в процессе выполнения func случайного ненулевого указателя, что в свою очередь приведет, скорее всего, к краху программы (это не говоря даже о неправильном размере сдвига стекового указателя на 2 байта в первом случае в противовес 4-м байтам во втором). Для 32-битных систем, для которых sizeof(int) равно sizeof(void *) (не знаю ни одной 32-х битной ОС, для которой это не так, но допускаю, что такие могут существовать), такой проблемы не существует. Однако, казалось бы, проблема возрождается вновь с появлением 64-битных систем, для которых sizeof(int) есть 4, а sizeof(void *) есть 8. Но принимая во внимание заодно задачу корректного выравнивания данных в 64-битных системах в стек вызова подпрограммы помещается 8 байт для любого аргумента (если его sizeof, конечно, меньше или равен 8 байтам), поэтому для func 0 и (void *) 0 будут выглядеть одинаково. Впрочем, хотя NULL, определенный как "(void *) 0", выглядит наследием древнего 16-битного прошлого, о его предназначении знать надо ![]() -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
GQU |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
что то я вас не пойму
так на 16ти битных машинах указатель, как и int занимает 16 бит, а не 32, хотя нет, там как то по другому все.. Это сообщение отредактировал(а) GQU - 24.8.2014, 16:15 |
|||
|
||||
feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Ничего подобного. На 16-битных машинах указатель представлял собой два 16-битных значения. При этом на 16-битных ОС первое представляло собой базовый адрес, второе - так называемый индекс. Итоговый адрес в адресном пространстве процесса получался путем сдвига базового значения на 4 позиции влево и приплюсовывания индекса, что-то вроде такого:
Таким образом можно было адресовать до 1 мегабайта памяти (что и было в DOS, например). Иными словами, то, что на 16-битных системах sizeof(int) был 2, совсем не означает, что и sizeof(void *) обязан быть 2. Реальный режим ![]() Это сообщение отредактировал(а) feodorv - 24.8.2014, 21:55 -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
GQU |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
допустим поместили в стек 4 нулевых байта для INT на 64 битной системе, а ОС помещает 8 байт, так не факт что остальные нулевые, хотя наверно они нулями как раз и заполняются или единицами для отрицательных чисел Раз начали говорить про указатели, спрошу, чтобы не создавать еще одну тему NULL это реальный нулевой адрес или нет??
мне кажется эти 2 байта и не нужны, потому что когда функция вызывается, компилятор знает типы параметров, он знает, что 0 - это INT и не пойдет искать еще 2 байта,хотя нет, в прототипе же будет написано, что это указатель ![]() Это сообщение отредактировал(а) GQU - 24.8.2014, 17:54 |
||||||
|
|||||||
feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Именно. В 64-х битных системах можно (на ассемблере) поместить в стек 4-х байтовую величину со сдвигом указателя на 8 байт, но смысла с в этом мало. Компиляторы все равно генерят код, в котором 4-х байтовое значение расширяется до 8-ми байтовой величины. Для знакового int оставшиеся 32 бита заполняются знаком, для беззнакового int - просто нулями. Компилятор - да, знает. Но об этом не знает функция func. В момент выполнения она надеется увидеть в стеке 4 полноценных байта адреса, а не два обрезанных. А что имеется в виду под реальным? Значение 0 в C/C++ принято присваивать тем указателям, которые (как бы) никуда не указывают. Потом, сравнивая значение указателя с 0, можно посмотреть, рабочий это указатель или нет. Например:
Вместо удобного 0 (а команды процессора, заносящие 0 в свои регистры, очень короткие и быстрые), можно было бы договориться о другом значении, например, ((void *) -1), но вот было принято вполне понятное решение о нуле. 0-ой байт вполне себе обычный байт в пространстве памяти процесса, и ему вполне можно было бы присваивать какое-то значение, если бы современные ОС специально не были бы так устроены, чтобы попытка чтения/записи по этому адресу не приводила бы к нарушению доступа (вылета программы). Более того, даже несколько первых (и последних) страниц процесса намеренно делают недоступными для чтения/записи, чтобы сказывались ошибки программирования. Вот представьте себе такой код:
В случае нехватки памяти (или некорректного обращения с кучей процесса) ptr будет указывать на первый байт процесса. Если бы не упомянутая защита, баг мог бы привести к непредсказуемым последствиям. Была у меня ситуация с VDD (то есть Virtual DOS Device под виндами, это вызов 32-х битной среды из 16-битной), когда запись по нулевому адресу прошла (в 32-х битном окружении). Но там, видимо, такой защиты не было предусмотрено, а жаль ![]() Так что ответ на Ваш вопрос будет таким: адрес реальный (при условии переданной процессу первой страницы памяти), но не предназначенный для использования (то есть для чтения/записи). -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
GQU |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
т.е для каждой программы свой процесс, для каждого процесса свой нулевой адрес?
так не факт, что если мы выйдем за пределы кучи, то попадем на эти страницы недоступные для записи/чтения Это сообщение отредактировал(а) GQU - 24.8.2014, 19:35 |
||||
|
|||||
feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Да, если не предприняты специальные меры.
Гм, что подразумевается под "выходом за пределы кучи"? Не факт, но если где-то возник NULL и некорректное с ним обращение, то с очень высокой вероятностью. Отлавливание багов - дело весьма занимательное, и я пока не знаю ни одного способа избежать их со 100% вероятностью. -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
GQU |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
закрываются адреса, которые уходят в минус? ![]() Как такое может быть?
тут я не могу понять Это сообщение отредактировал(а) GQU - 24.8.2014, 21:35 |
||||
|
|||||
feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Никогда не встречали такого кода:
А сколько будет (NULL - 1)? То есть что напечатает следующий код:
-------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
GQU |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
FFFFFFFF тогда получается нулевой байт не первый в выделенном процессе Это сообщение отредактировал(а) GQU - 24.8.2014, 21:52 |
|||
|
||||
feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
В смысле? В смысле зацикленности адресации памяти в силу ограниченности числа бит, выделенных на указатель? Ну так и unsigned int обладает тем же свойством))) Но поскольку отсчет идет все-таки от нулевого байта, то он-таки первый. Но спереди и сзади него тоже есть байты, этого не отнять. Только сзади находится как раз FFFFFFFF-ый ![]() -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
GQU |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
так это адрес нашего процесса или другова? или к другим процессам мы вообще доступа не имеем? PS: не увидел сообщения выше, не обновил страничку
ну тут таже фишка, как и в unsigned int, а то я понять не мог Это сообщение отредактировал(а) GQU - 24.8.2014, 22:21 |
||||
|
|||||
feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Ну, пока мы ведем речь лишь о нашем процессе. Но и в любом другом будет такая же ситуация. Адрес - это всего лишь число, номер байта в адресном пространстве процесса (нашего ли или не нашего). В современных ОС процессы отделены друг от друга, но существуют развитые способы межпроцессного взаимодействия. И, действительно, иногда приходится иметь дело с адресами другого процесса (что не означает, что в нашем процессе нет этого же адреса, но уже нашего). Все пользовательские процессы похожи друг на друга, всем выделяется адресное пространство с номерами байт 0-FFFFFFFF (для 32-х битных систем), но только это адресное пространство разное для разных процессов. Плоская модель памяти ![]() -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
GQU |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 13.2.2011 Репутация: нет Всего: нет |
что значит некорректное обращение с кучей можете это на примере полной программы, я что то не могу врубиться если бы не упомянутая защита, врятли бы указатель указывал на первый байт процесса, в случае некорректного обращения с кучей ![]()
А что, процессу могут и не передать первую страницу памяти?
Это же оно и есть? Неиспользуемая зона, для перехвата обращений по нулевым указателям Это сообщение отредактировал(а) GQU - 29.8.2014, 23:53 |
||||||
|
|||||||
Merlin_ua |
|
||||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 22.11.2006 Репутация: нет Всего: нет |
Насколько мне извесно в C NULL - это указатель на нулевой адрес, поэтому и определен ((void *)0) и не в коем случае нулевой значение какого-то объекта. В плюсах NULL оставили из-за совместимости, и не рекомендуют им пользоваться, а вместо него писать 0. Или же самому на свой страх и риск определить NULL и следить за его использованием. а то что
так здесь нужно смотреть на объявление функции, и компилятор должен по правилам приведения привести NULL к нужному типу, так что каких-то глюков с стеке быть не должно!!! По поводу нулевого указателя, так это скорее всего больше условность, обусловленная средой выполнения. Думаю в низкоуровневом программировании есть возможность использования адреса 0х00000000. Насчет
правильно выразиться для каждого процесса свой нулевой адрес. Опять таки, зависит от среды выполнения. Процесс может работать как в виртуальном адресном пространстве с контролем доступа, здесь у каждого процесса свое виртуальное адресное пространство так и в реальном адресном пространстве(системные процесс например) - здесь один нулевой адрес, и 0-1 = последний адрес а адресном пространстве цпу. Вообще, вся работа с памятью будет зависить от среды выполнения. Для высокоуровневого программирования указатель на 0 - это неинициализированный указатель, его использование вызовет ошибку. Также рекомендуется поменьше арифметики с адресами, так как после некоторых опяраций поведение программы непредсказуемы, например 0-1 может вызвать исключение, и если его не обработать - то крах процесса. |
||||
|
|||||
feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Это значит действие, приводящее к нарушению целостности кучи. Например, нечаянная запись в область структур кучи. В виндах даже можно проверить валидность кучи - HeapValidate Нарушить целостность кучи возможно, но специально прямо щас я это сделать не смогу. Просто в некоторых случаях HeapAlloc возвращает NULL, если куча разрушена, хотя свободная память в необходимом объеме все же есть. Тогда указатель ptr будет указывать на байт под номером один в адресном пространстве процесса.
К тому, чтобы указатель указывал на первый байт процесса, упомянутая защита никакого отношения не имеет. Вот если Вы возьметесь за разименовывание этого указателя (*ptr), тогда защита сработает. Уф. Изначально процессу передаются не все страницы памяти. Вернее, не только лишь все, мало какие. А в нашем случае оговариваемые страницы резервируются, но не передаются процессу. ЗЫ В C/C++ принято все отсчитывать от нуля. И очень сложно в Ваших вопросах адекватно воспринимать фразы типа "первый байт", "первая страница". -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
feodorv |
|
||||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Объявление функции (кстати, я его уже приводил):
Пожалуйста, из указанного объявления функции приведите аргумент 0 (а не упоминаемый Вами NULL) к нужному виду:
Это не условность. Значение 0 выбрано из соображений быстрой работы с регистрами процессора. Загружать какое-то ненулевое значение в регистры процессора дольше (и требует больше исполняемых кодов), чем просто ноль. Ноль так же подходит и по неким философским соображениям, на основании которых создавался язык C.
Использовать - в каком смысле. Но учтите, что современные пользовательские процессы все равно закрывают область вокруг нулевого байта на чтение/запись, все равно, с языка высокого уровня был скомпилирован процесс, или набит прямо в кодах.
Это как раз инициализированный указатель, инициализированный значением 0. Кстати, где Вы учились? Его разыменовывание вызовет ошибку. А использовать я его могу:
Давайте разберёмся с пользовательскими, пожалуйста. Пример, когда запись по адресу NULL прошла в пользовательском процессе, я уже описывал. -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||||||
|
|||||||||||
Merlin_ua |
|
||||||||||||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 22.11.2006 Репутация: нет Всего: нет |
Понял. В данном случае у Вас функция с переменным/незвестным колличеством и типом аргументов. В таких случаях вся ответственность на то, что попадает в стек и как его оттуда извлекать на программисте. А насчет
так 0 по умолчанию это int На платформе IA32 с компилятором от Microsoft или GCC в стек пойдет 4 байта.
Вы наверное имели ввду обнуление регистров а не загрузку. Загружать в регистр по времени что 0х00000000 что 0xffffffff одинаково, а вот обнулить регистр путем вычитания самого себя - быстрее чем загрузка 0х00000000. Насчет соображений и философии тоже с Вами согласен.
Не пользовательские процессы, а среда выполнения Runtime Environment, и Вы правы, всеравно на чем набит код. Среда ограничит действия кода. И будет закрыта не только область вокруг нулевого байта. Там много к чему еще будет ограничен доступ.
Ошибся. Неправильно выразил мысль. Я хотел сказать, доступ к памяти, на которую ссылается нулевой указатель вызовет ошибку. А что Вы так о моем образовании? Если у меня нет образования то что Вы хотите сказать? Что у мне нет места здесь? Или я не имею права поучаствовать в теме? Тема ж для новичков! Я не претендую на звание высоквалифицированного программиста. Я - не волшебник, я только учусь! Ну а Вы, если имеете солидную квалификацию, поправте где я не прав, научите как правильно!
Так я и не против! И про запись по NULL в пользовательском процессе тоже не спорю. Я лишь хотел хотел выразить мысль, что там, где идет работа с памятью и необходимо понимание протекающих с нею манипуляций нужно учитывать runtime environment. |
||||||||||||
|
|||||||||||||
feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Конечно)))
Так, навеяло))) Извините, если что... -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
Merlin_ua |
|
|||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 22.11.2006 Репутация: нет Всего: нет |
А что там в эпоху 16-разрядных систем? Если нетрудно - расскажите. Я в эти времена еще в школе учился на турбо-паскале на Поиске 2! Неужели стандарты тех времен не имели 0 по умолчанию? И что странного "(void *) 0"? Хотя что-то тут есть неудобовразумительное. В некоторых технологиях оговаривают, что NULL - это не 0, и использовать вместо NULL - 0 запрещают (по моему встречал такую оговорку в COM). В плюсах рекомендуют не использовать NULL или определить по собственному усмотрению.
|
|||
|
||||
feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Гм. А Вы вопрос ТС читали? А последующие соображения? А Вы в плюсах такой код пробовали:
???
Потому что в код C++ может быть включен заголовок, где NULL определен как "(void *) 0". Со всеми вытикающими... nullptr призван спасти ситуацию. Это сообщение отредактировал(а) feodorv - 30.8.2014, 13:30 -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
Merlin_ua |
|
||||||||||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 22.11.2006 Репутация: нет Всего: нет |
Читал. Вы наверно имеете ввиду следующие соображения:
Здесь хочу отметить следующее: 1. В случае с void func( ... ) контроль за аргументами функции полностью возлагается на программиста, и то, что у Вас там может не докладывается 2 нужных нулевых байта или же окажется какой-то мусор - это полностью ответственность программиста. 2.Я подозреваю, в настоящей теме, под 16-битной системой подразумевается Intel8086. Так вот. здесь не стоит путать физический и эффективный адрес. Указатели используют 16-разрядный эффективный адрес. Так что и sizeof(int) и sizeof(int*) имеют 2 байта. Манипуляции с 16-разрядным адресным регистром и сегментным регистром происходят на нижних уровнях - на системном уровне ОС.
В плюсах контроль над типами другой.
Полностью согласен. О NULL в плюсах даны конкретные рекомендации! |
||||||||||
|
|||||||||||
feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Да, поэтому программист и пишет:
Совсем не обязательно (по ссылке перечислено множество 16-битных процессоров). 16-битные процессоры разрабатываются до сих пор. Ну пусть будет Intel8086/Intel80286. Да ладно))) Far-указатели используют как базу, так и индекс. Каждая величина является 16-битным значением. В сумме - 32 бита при 16-битном выравнивании. См. модели памяти. Чувствуется, что Вы никогда не программировали на 16 битах на far-указателях. Модель данных, при которой int занимает 2 байта, а указатель - 4 байта, называется I16LP32, и применялась она не только на Интелах. Это сообщение отредактировал(а) feodorv - 31.8.2014, 01:22 -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
Merlin_ua |
|
||||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 22.11.2006 Репутация: нет Всего: нет |
Да, вы полностью правы! far указатели не использовал! Спасибо, что объяснили!
Почему не верный? в первом случае Вы передаете ((void *)0) во втором int. Ведь void func( ... ) говорит о том, типы и их количество не известны! |
||||
|
|||||
feodorv |
|
||||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Потому что func ожидает указатель. А не интегер. NULL служит указанием того, что список аргументов (указателей на строки) завершен. Такое было в моде одно время.
Именно. Значит func как-то должна знать, что ей передают. printf, например, использует форматную не только для того, чтобы оформить вывод, но и для того, чтобы понять типы переданных ей аргументов. Но даже здесь NULL может быть полезен (пример весьма искусственен, ну да ладно):
Последняя строка должна выглядеть так:
В случае func с переданным ей неопределённым числом указателей на строки как-то нужно сообщить функции число этих самых указателей. Это можно было бы сделать так:
не заботясь о числе аргументов, но завершая их список нулевым указателем. Когда func, выбирая указатели на строки из списка аргументов, натыкается на NULL, она понимает, что всё, список аргументов исчерпан. Когда она натыкается на 0 и ещё два каких-то случайных (скорее всего ненулевых) байта, то она продолжит обработку списка аргументов... -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||||||
|
|||||||||||
Merlin_ua |
|
||||||||||||||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 22.11.2006 Репутация: нет Всего: нет |
Я понял Вашу мысль. Но я также хочу что б Вы поняли и мою. Давайте вернемся к началу.
и здесь пояснение
Я так понимаю, что аргументы будут выбираться до тех пор, пока не встретится последовательность из 4-х байт равных 0х00. Тогда в случае
или же
Вы не только потеряете аргументы, но и приведете к краху программы. Я хочу донести мысль, что крах в случае с использованием void func( ... ) не из-за того, что int может быть двухбайтовым а NULL четырехбайтовым. И мысль
мне тоже не понятна. Хотя возможно это и так. |
||||||||||||||
|
|||||||||||||||
feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
И не донесете. Крах в случае намеренно некорректного программирования неизбежен. Иное дело, когда все запрограммировано на вид правильно, а оно рушится. Был поставленный ТС вопрос: зачем (void *) 0, а не просто 0. Прозвучал ответ: Все остальное - лишь иллюстрация к этому утверждению. В том числе и с двухбайтовым int и четырёх байтовым указателем при двубайтовом выравнивании (а именно это и стало исторической реальностью). Ровно такая же ситуация была бы и при однобайтовом int, двубайтовом указателе и однобайтовом выравнивании. Ровно такая же ситуация была бы и при четырех байтовом int, восьмибайтовом указателе и четырехбайтовом выравнивании. Поэтому для программиста важно определение NULL как (void *) 0, а не просто как 0. И ни по какой другой причине. В качестве примера взята функция func(...) которая работает с набором указателей на строки. Причем здесь a, b, c - это указатели на строки? ![]() Честно, мне лень лазить по интернету, чтобы подкрепить свои слова чужими. Вот на вскидку:
-------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
Merlin_ua |
|
||||||||||||||||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 22.11.2006 Репутация: нет Всего: нет |
По всей видимости да!
Определено стандартом или Ваше личное суждение?
Где оговорено, что в качестве аргументов исключительно указатели на строки??? Вы действительно не понимаете что такое a, b, c или притворяетесь ??? И если Вам не понятен мой пример, так это тоже лишь иллюстрация.
Будет! Также, как и в Вашем случае, когда Вы не докладываете два байта с стек
так как в стеке остается куча мусора.
Это похоже из той серии, где шла речь об образовании.
Это что? ответ на
или доказательство ликвидности Ваших примеров??? Выше я писал, что ликвидность лишь в частных случаях!! |
||||||||||||||||
|
|||||||||||||||||
feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Определено что?
То есть я обязан все разжевывать? Из примера не ясно? Ну извините.
Как краха программы не будет, так и потери аргументов. Это доказательство того, что не просто ![]() -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
![]() ![]() ![]() |
Правила форума "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. |