2017-02-22 9 views
2

Я пишу программу в C (32 бит), где я вывожу строку (длиной от 15 до 40 символов). Я решил использовать указатели и calloc вместо формального объявления массива. Моя программа полностью прекрасна, так что это не вопрос о логике или функции, мне просто интересно, что происходит под капотом моего кода на C.В C, являются ли символы в массиве (т. Е. Строка), хранящиеся в отдельных регистрах, или есть четыре символа для каждого регистра?

Мое понимание: Когда я использую calloc Я выделяющий раздел памяти в единицах байт. Переменные хранятся в ячейках памяти размером 32 бита (или 4 байта). В моей программе я пишу символы, используя мой указатель (т. Е. * Ptr = '!';), А затем увеличиваю точки (ptr ++;), чтобы перейти к следующему адресу памяти .

Мой вопрос: Если ячейки памяти 32 бита, и я пишу только 8-бит в этом месте памяти, являются остальные 24-бит не используется? Если нет, то используются указатели, указывающие на какой-то 8-разрядный суб-адрес памяти, указывающий на 8-разрядные разделы расположения памяти?

+1

Под «регистрами» вы подразумеваете «ячейки памяти»? –

+1

Вы пишете _Variables хранятся в регистрах размером 32 бита (или 4 байта) ._ Неверно, это скорее _Variables ** может быть ** сохранено в регистрах размером 32 бита (или 4 байта) ._ –

+2

«Если регистры 32-битные и я пишу только 8 бит в этот регистр, остальные 24 бита не используются? " является проблемой сборки и не указывается и не контролируется C. Существует множество возможностей. С точки зрения C, это не имеет значения. – chux

ответ

1

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

Кроме того, нет «следующих» регистров, регистры не имеют адресов. Файл регистра - это специальный аппаратный модуль, интегрированный в процессор и обычно называемый определенным набором битов.

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

+1

В настоящее время ключевое слово 'register' обычно игнорируется. См. [Этот вопрос SO] (http://stackoverflow.com/questions/578202/register-keyword-in-c) –

+2

'для обеспечения' - nopes, совсем нет, компилятор свободен и, вероятно, абсолютно игнорирует ключевое слово 'register'. –

+1

'обычно они будут просто сохранены в стеке. ', К сожалению, нет понятия« стека »в стандарте C, это до внедрения. –

1

Nopes, нет зарегистрироваться участие, в общем, они скудные ресурсы.

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

Я пишу символы, используя свой указатель (т.е. *ptr = '!';), а затем я увеличиваю точки (ptr++;), чтобы перейти к следующему регистра.

Не совсем так, вы говорите о местоположении памяти, на которую указывает указатель ptr. В случае, если ptr определяется как char *, ptr++ совпадает с ptr = ptr + 1, что увеличивает ptr на размер указывающего типа данных, char. Итак, после выражения ptr указывает на следующий элемент в памяти.

0

Вы можете указать в c, что var переходит в регистр, и большинство компиляторов оптимизирует это, но где переменная var зависит от какой переменной она есть.Локальные переменные будут идти в стек, функции распределения памяти должны положить его в кучу и дать вам адрес. Константы и строковые литералы войдут в сегмент данных только для чтения.

4

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

Говоря с точки зрения типичных реализаций товарного оборудования, хотя,

Мое понимание: Когда я использую calloc Я выделяющий раздел памяти в байтах.

Разумная характеристика.

Переменные хранятся в регистрах размером 32 бита (или 4 байта).

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

В некоторых случаях, связанных с конкретными конкретными конкретными условиями, некоторые переменные могут не иметь связанной ячейки памяти, а их значения сохраняются только в регистрах. Вообще говоря, однако, это never случай для переменных или выделенного пространства, которое было, было или когда-либо могло быть ссылкой указателем.

В моей программе я пишу символы, используя мой указатель (т. Е. * Ptr = '!';), А затем увеличиваю точки (ptr ++;), чтобы перейти к следующему регистру.

Нет, абсолютно нет. Приращение указателя заставляет его указывать на следующий элемент вашего динамического хранилища, измеренный в единицах размера заостренного типа. Это не имеет ничего общего с регистрами. Запись на объект, указывающий на объект, вероятно, связана с использованием регистров (потому что так работают ЦП), но в конечном итоге написанный символ заканчивается в обычной памяти.

Мой вопрос: Если регистры 32-бит, и я пишу только 8 бит в этот регистр, являются остальные 24-бит не используется?

Как я уже объяснил, этот вопрос основан на заблуждении. Цель вашей записи не является регистром. В любом случае между элементами, которые вы пишете, нет пробелов в памяти.

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

Если нет, то являются указателями, которые я использую, указывая на какое-то 8-разрядное распределение поддисков, указывая на 8-битные разделы регистров?

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

+0

Ну, мой ответ был забыт, прежде чем отправить его ^^. +1 для этого очень подробного ответа –

+0

Спасибо за подробный ответ. Я полностью использовал неправильную терминологию здесь, потому что я невежественен. Все ссылки на термин «регистр» должны читать «ячейка памяти». Итак, ячейки памяти адресованы байтам, а не словам? – MCHatora

+1

@MCHatora, как вы видите, правильная терминология необходима для точной коммуникации. Однако, даже заменяя «ячейку памяти» для «регистрации», у вас все еще есть недоразумение, адресованное в самом конце моего ответа: в C ячейки памяти (логически) * один * байтовый размер, а не четыре. Это не имеет никакого отношения к размеру родного языка базовой архитектуры. –

0

Как указал Сурав, вы неправильно используете регистры. Существует память под названием register, и в C. есть ключевое слово register. Но это не имеет особого отношения к указателям.

Типичный размер для выстроенного блока памяти составляет 16/32/64 бит в зависимости от вашей архитектуры. Вы думаете, что увеличиваете свой указатель на этот размер. Это неверно. В зависимости от того, какой тип указателя у вас есть, ваш шаг за шагом увеличивается. Это всегда размер вашего соответствующего типа данных в байтах.

*char получает увеличение на 1 байт, если вы ++ в то время как *(long long) получает увеличился на 8

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

Что вы думаете, что происходит, если вы объявите два char (или char и int в struct), их адреса отличаются друг от друга кратным размером блока и остальной памяти «впустую». Но поскольку вы выделили память, которую она предназначена для управления, вы можете упаковать ее подобно массиву.

0

Кажется, что существует путаница в отношении того, что такое регистр. Регистр - это место хранения в процессоре. Регистры имеют разные функции. Однако программисты, как правило, занимаются ОБЩЕЙ РЕГИСТРАТОЙ и Регистром статуса процесса.

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

Мое понимание: Когда я использую calloc, я выделяю секцию памяти в единицах байтов. Переменные хранятся в регистрах размером 32 бита (или 4 байта). В моей программе я пишу символы, используя мой указатель (т. Е. * Ptr = '!';), А затем увеличиваю точки (ptr ++;), чтобы перейти к следующему регистру.

Ваш компилятор может назначать переменные в регистрах, а не в памяти. Однако при каждом разыменовании указателя (например, * ptr) вам нужно получить доступ к памяти.

Если вы звоните

char *ptr = calloc (...) 

Переменная PTR может (или не может) быть помещен в регистр. Это все зависит от вашего компилятора. Значение, возвращаемое calloc, - это местоположение памяти, а не регистры.

Что вы должны сделать, чтобы узнать об этом, это создать код языка сборки из вашего компилятора. Большинство компиляторов имеют такую ​​возможность, и они, как правило, чередуют ваш код C сгенерированным кодом сборки.

Если вы:

В моей программе, я пишу символы, используя свой указатель (т.е. * PTR = «!';), а затем я увеличиваю точки (ptr ++;), чтобы перейти к следующему регистру.

Ваш сгенерированный код может выглядеть следующим образом (предполагается, что PTR отображается R1):

MOVB '!', (R0)+ 

Который на нескольких системах, перемещает значение '!' к адресу, на который указывает R0, затем увеличивает R0 на единицу.

Мой вопрос: если регистры являются 32-битными, и я пишу только 8 бит в этот регистр, оставшиеся 24-битные неиспользованные? Если нет, то есть ли указатели, которые я использую, указывая на какое-то 8-битное распределение поддисков, указывая на 8-битные разделы регистров?

В вашем случае вы не читаете и не записываете байты в регистры. Однако во многих системах есть подразделение РЕГИСТРАЦИЯ.

Смежные вопросы