Как следующая строка, интерпретируемая компилятором GCC:
printf("HELLO");
Я хочу знать это потому что, когда я запускаю следующую программу:
main()
{
printf(5+"Good Morning");
}
Программа печатает:
Morning
То, почему компилятор, запускает печать с шестого символа?
Здесь происходит множество вещей. Как уже говорили другие, printf()
ничего не "знает" о выражении 5+"Good Morning"
. Значение этого выражения определяется языком Си.
Во-первых, a+b
то же самое, что b+a
, поэтому 5+"Доброе утро"
то же самое, что "Доброе утро "+5
.
Итак, тип "Good Morning"
(т.е. строковый литерал) - "массив char
". В частности, "Good Morning"
- это массив из 13 символов (12 "обычных" символов, за которыми следует 0
). При использовании в большинстве выражений, тип массива в C "распадается" на указатель на его первый элемент, и двоичное сложение является одним из таких случаев. Все это означает, что в "Good Morning "+5
, "Good Morning"
распадается на указатель на его первый элемент, которым является символ G
.
Вот как выглядит память:
0 1 2 3 4 5 6 7 8 9 0 1 2
+---+---+---+---+---+---+---+---+---+---+---+---+---+
| G | o | o | d | | M | o | r | n | i | n | g | 0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+
Значение адреса G
плюс 5 - это указатель, который указывает на 5 мест от G
выше, то есть на M
. Таким образом, printf()
получает адрес, который находится по адресу M
. printf()
печатает его, пока не найдет 0
. Следовательно, на выходе вы видите Morning
.
То же, что и запись
char *ptr="Good Morning";
, за которой следует
printf( ptr + 5 );
, что означает & ptr [5]
, этот адрес указывает на «Утро»;
Добавление целого числа n к указателю приводит к адресу ptr + n * sizeof (type)
Он продвигает указатель ввода на 5 байт и, следовательно, пропускает слово "Good".
Это арифметика указателей в C.
Предположим, что базовый указатель строки "Good Morning" равен p, а 5+p =p+5 и указывает на букву M.
Следовательно, на вход printf подается указатель на букву M.
Потому что «Доброе утро»
- это указатель на строку (фактически на ее первый байт), и добавление 5 к этому указателю дает указатель на 5-й символ. Строки C заканчиваются нулем, так что в любом случае printf
выполняется до тех пор, пока в конце не встретит ноль.
Это артефакт арифметики указателей языка C; printf
- всего лишь отвлекающий маневр.
Тип строкового литерала (например, «Доброе утро
») - const char *
. Ваш код эквивалентен:
const char *p = "Good morning";
p = p + 5;
printf(p);
Добавление указателя и целого числа дает указатель на 5-й элемент в последовательности.