2010-02-25 3 views
7

Я читал the following text from Stanford's Programming Paradigms class, и я заметил, что когда автор использует класс строк, конструктор делает вызов функции выглядит следующим образом:Elementary C++ Тип Путаница

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

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

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

+0

'strlen()' фактически возвращает 'size_t', а не' int'. Одно из важных отличий заключается в том, что 'size_t' является неподписанным типом, т. Е. Он может содержать только положительные числа. Это имеет смысл - длина строк может быть 0, 1 или 30000 символов, но никогда -7. – MSalters

ответ

11

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

+1

+1 для правильного именования. :) –

+0

Если 'int' - -ve, он может быть и ниже в памяти; поэтому он должен быть 'unsigned int ', чтобы результат был * всегда * выше в памяти. [Извините, если это nitpicking;] – legends2k

+0

@ legendends2k Это правда, хотя strlen() никогда не должен возвращать отрицательное значение, поэтому конкретный анализ кода здесь приведет к тому, что второй аргумент всегда будет больше или равен первому. – ChrisH

0

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

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 
0

как же второй аргумент может передать (символ * + INT)

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

2

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

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

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

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. 
4

Бинарные аддитивные операторы + и - может быть использован, когда один аргумент является указателем любого полного типа (скажем, 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.

0

Я думаю, что это может быть слишком ответственно.

В:

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

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

(str + strlen(str)) является указателем на конец строки.

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

+0

Указатель не является (всегда) целым числом. Например, на x86-16 это пара целых чисел. – MSalters