Элементарный C ++ Type Confusion - PullRequest
       4

Элементарный C ++ Type Confusion

7 голосов
/ 25 февраля 2010

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

string::string(const char* str) {
    initializeFrom(str, str + strlen(str));
}

Если функция initializeFrom принимает два аргумента char *, почему второй аргумент может передавать (char * + int) в char * и правильно ли он работает? Как система типов интерпретирует это утверждение?

Заранее спасибо.

Ответы [ 6 ]

11 голосов
/ 25 февраля 2010

Это называется арифметикой указателей. Char * + int приводит к символу *, который находится в памяти выше символов int.

4 голосов
/ 25 февраля 2010

Двоичные аддитивные операторы + и - могут использоваться, когда один аргумент является указателем на любой полный тип (скажем, T* p), а другой аргумент является целым числом (скажем, i). Они реализуют так называемую арифметику указателей .

Компилятор предполагает, что указатель указывает на элемент некоторого массива (скажем, T array[N]). Операция создает указатель на другой элемент массива, который находится на расстоянии i элементов от исходного элемента. Можно «переместить» указатель в любом направлении, то есть к началу массива или к концу массива. Например, если p указывает на array[3], то p + 4 будет указывать на array[7].

Операция действительна только тогда, когда результат указывает на существующий элемент массива или один за последним элементом массива, т. Е. С учетом массива T array[N], можно создавать указатели на элементы от array[0] до мнимый элемент array[N]. Любые попытки пересечь эти границы с использованием арифметики указателей приводят к неопределенному поведению.

Тип T должен быть полным, это означает, что арифметику указателей нельзя использовать с указателями void *, например, даже если некоторые компиляторы допускают это как расширение (обрабатывая указатели void * как эквивалентные char * указатели).

В дополнение к бинарным аддитивным операторам, арифметика указателей также включает префиксные и постфиксные унарные операторы ++ и -- (применяемые к указателям), а также составные операторы присваивания += и -= (с указателями на их слева и целые числа справа).

В вашем случае выражение str + strlen(str) создаст указатель типа char *, который указывает на завершающий символ \0 в строке str.

2 голосов
/ 25 февраля 2010

Помните, что указатель - это просто переменная, которая содержит адрес памяти. Таким образом, вы можете добавить значения в адрес памяти. Адрес памяти - это число.

Когда вы добавляете 1 к указателю определенного типа, он фактически добавляет 1 * sizeof (тип). Когда вы добавляете любое значение N, оно фактически добавляет N * sizeof (тип).

Рассмотрим следующий пример:

int x[5] = {0,1,2,3,4};
int *p = &(x[0]);//point to the first element
p = p + 1;//p now points to the second element.
0 голосов
/ 25 февраля 2010

Я думаю, что это может быть переоценено.

В:

 initializeFrom(str, str + strlen(str));

str - указатель на начало строки.

(str + strlen(str)) - указатель на конец строки.

Имейте в виду, что str (указатель символа) - это просто целое число ((int), (long), (long long) в зависимости от архитектуры), которое идентифицирует местоположение в памяти.

0 голосов
/ 25 февраля 2010

почему второй аргумент может передавать (char * + int)

Он по-прежнему передает char *, указывающий на strlen(str), после первоначально указанного места.

0 голосов
/ 25 февраля 2010

Первый аргумент указывает на начало массива char, а второй указывает NULL char в конце массива char.

const char *str = "abc";
char *start = str; // start now points to the first char.
char *end = str + strlen(str); // end now points to the null char at the end.

Вы можете подтвердить это, напечатав:

printf("%c %d",*start,*end); // will output: a 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...