Как точно типы данных представлены в компьютере?

Я - начинающий программист, читающий K&R, и я чувствую, как будто книга принимает много предыдущих знаний. Одним аспектом, который смущает меня, является фактическое представление, или если я говорю что существование переменных в памяти. Что точно тип данных указывает для переменной? Я не слишком уверен в том, как к слову этот вопрос..., но я задам несколько вопросов, и возможно кто-то может придумать когерентный ответ для меня.

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

Кроме того, это означает, что тип данных "символ" прекрасен только для использования, когда мы просто присваиваем значение переменной вручную, такой как символ c =, когда мы определенно знаем, что у нас только будет 256 возможных символов ASCII?

Кроме того, каково фактическое важное различие между "символом" и "интервалом"? Если мы можем использовать "международный" тип вместо "символьного" типа, почему мы решаем использовать один по другому в определенное время? Это должно сохранить "память" (я использую кавычки, поскольку я не делаю на самом деле, как "память" точно работает).

Наконец, как точно 256 доступных значений полученного символа типа? Я считал что-то о модуле 2^n, где n = 8, но почему это работает (что-то, чтобы сделать с двоичным файлом?). Какова часть по модулю "по модулю 2^n" средний (если она имеет какое-либо отношение к арифметике в остаточных классах, я не вижу отношения...)?

11
задан Brian Tompsett - 汤莱恩 19 November 2015 в 16:44
поделиться

9 ответов

По сути, системная память - это одна огромная последовательность битов, каждый из которых может быть либо «включен», либо «выключен». Остальное - условности и интерпретации.

Во-первых, нет возможности напрямую обращаться к отдельным битам; вместо этого они сгруппированы в байты, обычно в группы по 8 (есть несколько экзотических систем, где это не так, но вы можете пока игнорировать это), и каждый байт получает адрес памяти. Таким образом, первый байт в памяти имеет адрес 0, второй - адрес 1 и т. Д.

Байт из 8 бит имеет 2 ^ 8 возможных различных значений, которые можно интерпретировать как число от 0 до 255 (беззнаковый байт), или как число от -128 до +127 (байт со знаком), или как символ ASCII. Переменная типа char по стандарту C имеет размер 1 байт.

Но байты слишком малы для многих вещей, поэтому были определены другие типы большего размера (т. Е. Они состоят из нескольких байтов), и процессоры поддерживают эти разные типы с помощью специальных аппаратных конструкций. int в настоящее время обычно составляет 4 байта (хотя стандарт C не определяет его, а целые числа могут быть меньше или больше в разных системах), потому что 4 байта составляют 32 бита, и до недавнего времени это было то, что основные процессоры поддерживали их «размер слова».

Таким образом, переменная типа int имеет размер 4 байта. Это означает, что когда его адрес памяти, например 1000, то он фактически охватывает байты по адресам 1000, 1001, 1002 и 1003. В C можно одновременно адресовать и эти отдельные байты, и именно так переменные могут перекрываться.

В качестве примечания: большинство систем требуют, чтобы более крупные типы были «выровнены по словам», то есть их адреса должны быть кратны размеру слова, потому что это упрощает работу оборудования. Таким образом, невозможно, чтобы переменная int начиналась с адреса 999 или адреса 17 (но 1000 и 16 в порядке).

4
ответ дан 3 December 2019 в 03:52
поделиться

Согласно "stdio.h" возвращаемое значение getchars () - int, а EOF определяется как -1. В зависимости от фактического кодирования могут встречаться все значения между 0..255, там для unsigned char недостаточно для представления -1 и используется int. Вот хорошая таблица с подробной информацией http://en.wikipedia.org/wiki/ISO/IEC_8859

0
ответ дан 3 December 2019 в 03:52
поделиться
  • В C, EOF - это «маленькое отрицательное число».
  • В языке C тип char может быть беззнаковым, что означает, что он не может представлять отрицательные значения.
  • Для беззнаковых типов, когда вы пытаетесь присвоить им отрицательное значение, они преобразуются в беззнаковое значение. Если MAX - максимальное значение, которое может содержать беззнаковый тип, то присвоение -n такому типу эквивалентно присвоению MAX - (n% MAX) + 1 ] к нему. Итак, отвечая на ваш конкретный вопрос о прогнозировании, «да, вы можете». Например, предположим, что char не имеет знака и может содержать значения от от 0 до 255 включительно. Тогда присвоение -1 символу эквивалентно присвоению ему 255 - 1 + 1 = 255 .

С учетом вышеизложенного, чтобы иметь возможность хранить EOF в c , c не может быть типа char . Таким образом, мы используем int , потому что он может хранить «небольшие отрицательные значения». В частности, в C int гарантированно хранит значения в диапазоне -32767 и +32767 . Вот почему getchar () возвращает int .

Кроме того, означает ли это, что тип данных «char» можно использовать только тогда, когда мы просто присваиваем значение переменной вручную, например, char c = 'a', когда мы точно знаем, что у нас будет только 256 возможных символов ASCII?

Если вы присваиваете значения напрямую, то стандарт C гарантирует, что выражения типа 'a' уместятся в char . Обратите внимание, что в C 'a' имеет тип int , а не char, но можно сделать char c = 'a' , потому что 'a' может соответствовать типу char .

На ваш вопрос о том, какой тип должна содержать переменная, ответ таков: используйте любой тип, который имеет смысл. Например, если вы считаете или смотрите на длину строк, числа могут быть только больше или равны нулю. В таких случаях следует использовать беззнаковый тип. size_t является таким типом.

Обратите внимание, что иногда бывает сложно определить тип данных, и даже «профи» могут ошибаться. Формат gzip , например, сохраняет размер несжатых данных в последних 4 байтах файла. Это не работает для огромных файлов размером> 4 ГБ, что в наши дни является довольно распространенным явлением.

Будьте осторожны с терминологией. В C a char c = 'a' присваивает целочисленное значение, соответствующее 'a' к c , но это не обязательно должно быть ASCII. Это зависит от того, какую кодировку вы используете.

О части "по модулю" и 256 значений типа char : если у вас есть n двоичных битов в типе данных, каждый бит может кодировать 2 значения: 0 и 1. . Итак, у вас есть 2 * 2 * 2 ... * 2 ( n раз) доступных значений, или 2 n . Для беззнаковых типов любое переполнение четко определено, это как если бы вы разделили число на (максимально возможное значение + 1) и взяли остаток. Например, предположим, что unsigned char может хранить значения 0..255 (всего 256 значений). Затем присвоение 257 беззнаковому символу в основном разделит его на 256, возьмет остаток (1) и присвоит это значение переменной. Однако это отношение верно только для беззнаковых типов. См. мой ответ на другой вопрос для получения дополнительной информации.

Наконец, вы можете использовать массивы char для чтения данных из файла на C, даже если вы можете в конечном итоге нажать EOF , потому что C предоставляет другие способы обнаружения EOF без необходимости явно читать его в переменной, но вы узнаете об этом позже, когда прочитаете о массивах и указателях (см. fgets () , если вам интересен один пример).

1
ответ дан 3 December 2019 в 03:52
поделиться

Красота K&R в его лаконичности и удобочитаемости, писатели всегда должны идти на уступки ради своих целей; Вместо того, чтобы быть справочным руководством на 2000 страниц, он служит основным справочником и отличным способом выучить язык в целом. Я рекомендую Харбинсона и Стила "C: A Reference Manual" в качестве отличного справочника по C для получения подробной информации, и, конечно же, стандарта C.

У вас должно быть желание погуглить это. Переменные представлены в памяти в определенных местах и ​​известны программе, частью которой они являются, в заданной области.Символ обычно хранится в 8 битах памяти (на некоторых редких платформах это не обязательно так). 2 ^ 8 представляет 256 различных возможностей для переменных. Различные ЦП / компиляторы / и т. Д. Представляют собой базовые типы int, длинные разного размера. Я думаю, что стандарт C может указывать для них минимальные размеры, но не максимальные. Я думаю, что для double он определяет как минимум 64 бита, но это не мешает Intel использовать 80 бит в блоке с плавающей запятой. В любом случае, типичные размеры в памяти на 32-битных платформах Intel будут 32 бита (4 байта) для unsigned / signed int и float, 64 бита (8 байт) для double, 8 бит для char (подписанный / беззнаковый). Вы также должны посмотреть выравнивание памяти, если вас действительно интересует эта тема. Вы также можете получить точный макет в вашем отладчике, получив адрес вашей переменной с помощью оператора «&», а затем взглянув на этот адрес. Платформы Intel могут немного запутать вас при просмотре значений в памяти, поэтому, пожалуйста, ищите также прямой / прямой порядок байтов. Я уверен, что переполнение стека также содержит хорошие резюме.

0
ответ дан 3 December 2019 в 03:52
поделиться

Я не собираюсь полностью отвечать на Ваш вопрос, но я хотел бы помочь Вам понять переменные, так как у меня были те же проблемы с их пониманием, когда я начал программировать самостоятельно.

На данный момент не беспокойтесь об электронном представлении переменных в памяти. Думайте о памяти как о непрерывном блоке из 1-байтовых ячеек, в каждой из которых хранится битовая модель (состоящая из 0s и 1s).

Только глядя на память, нельзя определить, что в ней представляют собой биты! Это просто произвольные последовательности 0s и 1s. Именно ВЫ определяете, КАК интерпретировать эти битовые паттерны! Взгляните на этот пример:

int a, b, c;
...
c = a + b;

Можно было бы записать и следующее:

float a, b, c;
...
c = a + b;

В обоих случаях переменные a, b и c хранятся где-то в памяти (и Вы не можете сказать их тип). Теперь, когда компилятор компилирует Ваш код (то есть транслирует Вашу программу в машинные инструкции), он следит за тем, чтобы "+" в первом случае транслировался в integer_add, а во втором - в float_add, таким образом, чтобы CPU корректно интерпретировал битовые паттерны и выполнял то, что Вы захотите.

Типы переменных подобны очкам , которые позволяют процессору смотреть на битовые паттерны с разных точек зрения.

3
ответ дан 3 December 2019 в 03:52
поделиться

G 'da дня,

Чтобы углубиться, я настоятельно рекомендую превосходную книгу Чарльза Петцольда " Code "

"Она охватывает больше, чем то, что вы спрашиваете, и все это приводит к лучшему пониманию того, что на самом деле происходит под обложками.

HTH

-121--2921092-

Можно использовать любые пакеты для создания флэш-карт, а затем сохранить выходные данные в формате pdf (например, используйте pdflatex ). Затем создайте в Latex другой документ, в котором используется пакет pdfpages и используется параметр nup для печати двух страниц на страницу. Pdfpages имеет множество опций для точной настройки макета страницы. Это дает вам всю мощь других пакетов для вашего использования.

-121--1577996-

Действительно, типы данных являются абстракцией, которая позволяет языку программирования рассматривать несколько байт по какому-либо адресу как некий числовой тип. Рассматривайте тип данных как объектив, который позволяет видеть часть памяти как int или float. На самом деле, это все просто кусочки к компьютеру.

1
ответ дан 3 December 2019 в 03:52
поделиться

G'day,

, чтобы идти глубже, я очень рекомендую Charle Petzold's отличная книга « код »

он охватывает больше, чем вы спрашиваете, все, что приводит к лучшему Понимание того, что на самом деле происходит под крышками.

HTH

2
ответ дан 3 December 2019 в 03:52
поделиться

Один аспект, который меня смущает, это фактическое представление, или я должен сказать существование, переменных в памяти. Что именно определяет тип данных Для переменной?

на уровне станка, разница между int и CHAR является только размером, или количество байтов, памяти, выделенной для него языком программирования. Отказ В C, IIRC A Char - это один байт, в то время как INT составляет 4 байта. Если бы вы были «смотреть» на них внутри самой машины, вы увидите последовательность битов для каждого. Возможность лечить их как INT или или , зависит от того, как язык решает интерпретировать их (именно поэтому это возможно, чтобы его можно было превратить взад-вперед между двумя типами).

При использовании GetChar () мне сказали, что Лучше использовать тип «int», чем Введите «CHAR» из-за того, что «int» может держать больше значений, пока «char» может Держите только 256 значений.

Это потому, что существует 2 ^ 8 или 256 комбинаций 8 битов (потому что немного может иметь два возможных значения), тогда как существуют 2 ^ 32 комбинации 32 бита. Констанция EOF (как определено C) является отрицательным значением, не входящим в диапазоне 0 и 255. Если вы пытаетесь назначить это отрицательное значение для Char (это сжимая 4 байта в 1), биты более высокого порядка Будет потерян, и вы получите действительное значение CAR, которое не то же самое, что и EOF. Вот почему вам нужно хранить его в INT и проверять перед литьем в чар.

Также это означает, что данные Тип «CHAR» только в том, чтобы использовать только когда Мы просто назначаем ценность Переменная вручную, например 0char C = «А», когда мы определенно знаем, что мы будет иметь только 256 возможных ASCII Персонажи?

Да, особенно в том случае, вы присваиваете символьное литерату.

Кроме того, какова фактическая важная Разница между «Char» и «int»? Если мы можем использовать тип «int» вместо «Чем» тип, почему мы решили использовать Один над другим в определенные времена?

Самое главное, вы бы выбрали int или Char на уровне языка в зависимости от того, хотели ли вы относиться к переменной в виде номера или Письмо (переключатель, вам нужно будет отбрасывать на другой тип). Если вы хотите целочисленное значение, которое заняло меньше места, вы можете использовать короткий int (который, как я считаю, это 2 байта), или если вы были действительно обеспокоены использованием памяти, вы можете использовать CHAR , хотя в основном это не нужно.

Редактировать : вот ссылка , описывающая различные типы данных в C и модификаторах, которые могут быть применены к ним. См. Таблицу в конце для размеров и диапазонов стоимости.

5
ответ дан 3 December 2019 в 03:52
поделиться

Я использовал информацию на этом посту для небольшого образца, который я строил. Это код, который я использовал, когда я начал воспроизведение, чтобы предотвратить остановку звука:

AudioSession.Category = AudioSessionCategory.MediaPlayback;

И когда приложение закончило воспроизведение, чтобы сбросить исходное значение:

AudioSession.Category = AudioSessionCategory.SoloAmbientSound;

Полный образец здесь:

http://github.com/migueldeicaza/monotouch-samples/tree/master/StreamingAudio/

-121--1513805-

Отладка операционной системы не для слабонервных. Поскольку выполняется отладка ядра, ваши параметры будут довольно ограниченными. Большое количество инструкций printf - это один трюк, и, кроме того, это зависит от того, что именно «операционная система» отлаживается, мы можем говорить о

  • Файловая система
  • Драйверы
  • Управление памятью
  • Вход/выход Raw Disk
  • Ввод/вывод экрана
  • Ядро

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

Некоторые ядра могут (не все из них имеют их) включать простой отладочный монитор, на самом деле, если я правильно помню, в книге под названием «Разработка собственной 32-битной операционной системы» Ричарда A Burgess, Sams publishing, он включил отладочный монитор, который отображает различные состояния CPU, регистры и так далее.

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

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

Надеюсь, что это поможет, С уважением, Том.

-121--1577282-

Отличные вопросы. K & R был написан в те времена, когда было гораздо меньше знать о компьютерах, и поэтому программисты знали гораздо больше об оборудовании. Каждый программист должен быть знаком с этим, но (понятно) многие начинающие программисты не являются.

В Университете Карнеги-Меллон они разработали целый курс, чтобы заполнить этот пробел в знаниях, для которого я был TA. Я рекомендую учебник для этого класса: «Компьютерные системы: перспектива программиста» http://amzn.com/013034074X/

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

В основном, компьютеры хранят всю информацию - будь то в памяти (ОЗУ) или на диске - в двоичном формате, системе чисел base-2 (в отличие от десятичной, которая является базовой 10). Одна двоичная цифра называется битом. Компьютеры, как правило, работают с памятью в 8-битных фрагментах, называемых байтами.

Символ в C - это один байт.Значение int обычно равно четырем байтам (хотя оно может быть различным на разных машинах). Таким образом, символ может содержать только 256 возможные значения, 2 ^ 8. int может содержать 2 ^ 32 различных значений.

Для получения дополнительной информации обязательно прочитайте книгу или прочитайте несколько страниц Википедии:

Best of luck!

UPDATE с информацией о модульной арифметике по запросу:

Во-первых, прочитайте о модульной арифметике: http://en.wikipedia.org/wiki/Modular_arithmetic

В основном, в двухразрядной системе дополнения n-разрядное число действительно представляет класс эквивалентности целых чисел по модулю 2 ^ n.

Если кажется, что это усложняет его, а не меньше, то ключевые вещи, которые нужно знать, просто:

  • Беззнаковое n-разрядное число содержит значения от 0 до 2 ^ n-1. Значения «обернуться», так что, например, когда вы сложите два числа и получите 2 ^ n, вы действительно получите ноль. (Это называется «переполнением».)
  • Число со знаком n-бит содержит значения от -2 ^ (n-1) до 2 ^ (n-1) -1. Числа по-прежнему оборачиваются, но наибольшее число оборачивается до самого отрицательного, и оттуда начинается отсчет в сторону нуля.

Таким образом, для 255 можно 0 беззнаковый байт (8-битовое число). 255 + 1 оборачивается к 0. 255 + 2 заканчивается как 1 и так далее. Байт со знаком может быть от -128 до 127. 127 + 1 заканчивается как -128. (!) 127 + 2 заканчивается как -127 и т.д.

10
ответ дан 3 December 2019 в 03:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: