Массив символов не может быть вычтен из указателя, но один указатель может быть вычтен из другого указателя, если оба указателя указывают на элементы одного и того же массива или один после последнего элемента массива.
Из C стандарта (6.5.6 Аддитивные операторы)
9 Когда вычитаются два указателя, оба должны указывать на элементы одного и того же объекта массива или один после последний элемент объекта массива; Результатом является разница индексов двух элементов массива. Размер результата определяется реализацией, а его тип (целочисленный тип со знаком) ptrdiff_t определен в заголовке. Если результат не может быть представлен в объекте этого типа, поведение не определено. Другими словами, если выражения P и Q указывают, соответственно, на i-й и j-й элементы объекта массива, выражение (P) - (Q) имеет значение i-j, если значение вписывается в объект типа ptrdiff_t. Более того, если выражение P указывает либо на элемент объекта массива, либо на один элемент после последнего элемента объекта массива, а выражение Q указывает на последний элемент того же объекта массива, выражение ((Q) +1) - (P) имеет то же значение, что и ((Q) - (P)) + 1 и - ((P) - ((Q) +1)), и имеет нулевое значение, если выражение P указывает на одну точку после последний элемент объекта массива, хотя выражение (Q) +1 не указывает на элемент объекта массива.106
Таким образом, возникает вопрос: что такое s
в выражении found-s
?
Стандартные ответы C (6.3.2.1 L-значения, массивы и обозначения функций)
3 За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, или строковый литерал, используемый для инициализации массива, выражение, имеющее тип '' массив типа '', преобразуется в выражение с типом '' указатель на тип '', указывающее на начальный элемент объекта массива и не является lvalue. Если объект массива имеет класс хранения регистров, поведение не определено.
Таким образом, в приведенном выше выражении s
преобразуется в указатель на его первый элемент, и фактически выражение может быть эквивалентно переписано для ясность вроде
found - &s[0]
Но, конечно, зная это неявное преобразование указателей массива в указатели, проще написать
found - s
Результатом выражения является количество элементов массива между двумя указателями.
Иногда новички допускают следующую ошибку, ничего не зная о таком преобразовании. Они пишут, например,
char s[] = "Hello";
if ( s == "Hello" )
{
// ...do something
}
Однако в условии оператора if сохраненные строки не сравниваются. Сравниваются адреса первого элемента массива s и первого элемента строкового литерала. Поскольку массив и литерал занимают разные области памяти, результат условия оценивается как ложное.