Арифметики скрытых указателей нет, но я подозреваю, что вам нужен более подробный ответ, чем этот.
Если у вас есть функция:
void foo() {
char * bar = "Hello World";
}
На самом деле есть два блокапамяти, которая входит в игру:
- Во-первых, 12 байтов используются для хранения «Hello World» (1 байт для каждой буквы плюс нулевой байт в конце).Компилятор поместит это в сегмент данных.Эта память (местоположение и значения) устанавливается во время компиляции и не может быть изменена во время выполнения (если вы попытаетесь, это приведет к segfault).
- Второе местоположение - указатель на данные, это
bar
переменная.Когда ваша программа вызывает foo()
, она выделяет достаточно стекового пространства (4 байта на 32 бита) для размещения этой области памяти, и она инициализируется с расположением фактических данных.Это происходит каждый раз, когда вы забавляетесь foo()
.
Более того, если вы выполните инструкцию, подобную этой, позже в функции:
bar = "Good bye";
Вы не меняете данные«Привет, мир», «До свидания».На самом деле вы просто получаете 3-й кусок памяти в сегменте данных с «Good bye» в нем (все еще выделяется во время компиляции), а затем указатель (bar) устанавливается в это место при выполнении этой строки.
Еще один метод создания «строк» (символьных массивов):
void foo() {
char bar[] = "Hello World";
}
Это не так же, как первый (хотя и закрытый).В этом методе у вас все еще есть две переменные, за исключением того, что фактические данные, о которых вы беспокоитесь («Hello World» + нулевой байт), выделяются и инициализируются в стеке программы.
Вы можете увидеть разницу вскомпилированную сборку, запустив gcc -S test.c
и затем прочитав test.s
.
В какой-то момент вам захочется взглянуть на строковые функции C .
Они нажимаютПри использовании этих функций следует помнить, что они вообще не знают, каковы длины ваших символьных массивов, а выясняют, исходя из того, где находится первый нулевой символ (значение часового).