Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатели, строки, классы и пр. Си++ новичкам посвящается... 
V
    Опции темы
TarasProger
Дата 12.8.2015, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет



Цитата(ManiaK @  9.8.2005,  14:35 Найти цитируемый пост)
Как известно, строки в Си заканчиваются нулевым символом (символом, имеющим код 0). Любая строка, взятая в двойные кавычки по определению заканчивается этим символом и потому размер "Dinamic String" не 14, а 15. Это нужно для того, чтобы программа, использующая эту строку, знала, где она кончается. Можно, конечно, для каждой строки таскать свою переменную, в которой содержится число символов, но это очень неудобно в тех случаях, когда приходится оперировать десятками различных строк. В Pascal'е другой принцип - первый символ строки содержит не код первого символа, а число символов в строке. Но тогда для стандартного байтного набора символов максимально возможной длинной строки будет 255 символов, а этого бывает мало.
Количество символов можно хранить в двух первых байтах, и в четырёх, и в восьми, и даже в sizeof(char*) первых байт, чтоб уж точно хватило на любую возможную строку. Проблема здесь другая:
1. Если на одной платформе будет количество символов в 4-х первых байтах, а на другой - в восьми, и такая строка будет как есть сохранена в бинарный файл, или передана по сети, то код первого символа точно прочитается не правильно, а может быть не правильно интерпретируется и количество символов.
2. Если на одной платформе один порядкок байт, а на другой - совсем другой, то не правильно интерпретируется количество символов.
Терминальный же ноль в этом плане универсален. И что неудобного в структуре 
Код
struct 
{
 int count;
 char *p;
};
?

Добавлено через 7 минут и 40 секунд
Цитата(ManiaK @  9.8.2005,  14:35 Найти цитируемый пост)
   Си - самый логичный с точки зрения архитектуры ЭВМ язык программирования. Практически всё, что можно сделать на ассемблере, можно сделать и на Си. Не верите? Смотрите:

Выделить всёкод C++
1:
2:
    
    unsigned char* pch = (unsigned char*)0xBC00;
    memcpy(pch, _T("Hello, World!"), 26);

Вот только вызов функции, возможно на языке ассемблера написанной, - не показатель. А попробуйте помимо функций и асм-вставок вызхвать программное прерываение, или присвоить значение регистру процессора. Или соверешить переход в зависимости не от результата сравнения, а от флага результата арифметической операции, например, в случае переполнения. На c нельзя делать вообще ничего, что можно делать на языке ассемблера. А так то свой memcpy можно написать и для паскаля, и для бейсика, и для любого другого языка, допускающего побочные эффекты подпрограмм, даже стекового.

Добавлено через 14 минут и 50 секунд
Цитата(ManiaK @  9.8.2005,  14:35 Найти цитируемый пост)
Разумеется, всё это сказано только для общего развития, подобные вещи принято и правильно писать на Ассемблере, так как только в нём можно наиболее эффективно работать с аппаратурой напрямую.
И это на фоне утверждения о том, что на c якобы можно делать всё тоже самое. Эффектичность чистого c кода, кстати, обязана быть максимально возможной, это было главное требование ТЗ на язык. Максимальная эффктивность кода + возможность делать всё тоже самое, что и на языке ассемблера = на ассемблере нельзя ничего делать эффективнее, в лучшем случае столько же эффективно, но не эффективнее. Но почему то c нуждается в поддержке вставок на языке ассемблера.

PM MAIL   Вверх
TarasProger
Дата 12.8.2015, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет



Цитата(ManiaK @  9.8.2005,  14:35 Найти цитируемый пост)
Вспоминая себя во времена моего изучения Си++, я часто удивляюсь, насколько логично проходило это изучение. На первых порах я брал чужие программы и пытался их модифицировать; классическая схема: сам пока ничего не можешь, но что-то творить хочется. Вскоре мне это, разумеется, надоело, я залез в книги и начал пробовать писать самостоятельно. Но как я писал - это заслуживает отдельного внимания! Я думаю, многие так начинали свой путь программиста...
Я первые месяца полтора не то что изменить что либо в чужой программе, а даже понять в них хоть что то не мог, а мог как раз только писать сам. Потом со знанием алгоритмов и их классов пришло и умение читать чужие программы. Умение же что то менять в чужих программах пришло только лет через 7 с умением абстрагироваться от конркретного стиля, а раньше я мог только прочитать, полностью переписать и тогда уже дополнять.

PM MAIL   Вверх
TarasProger
Дата 14.8.2015, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет



Цитата(ManiaK @  9.8.2005,  14:35 Найти цитируемый пост)
тут указание константы в квадратных скобках явно свидетельствует об том, что будет создан статический массив.
Хочу отметить, что "статический массив" здесь - не синоним "статическая переменная, являющаяся массивом", хотя массив - тоже переменая. Массивы бывают:
1. Константные, в этом случае и количество элементов массива - константа, и сами элементы - константы.
2. Статические, в этом случае количество элементов массива - константа, но сами элементы - переменные. Весь массив при этом может лежать на стеке, если это не противорчит ни стандарту языка, ни спецификации конкретного диалекта, тогда при слишком большой глубине рекурсии рекурсивной функции с локальным массивом может происходить переполнение. В программах на Object Pascal я данное явление наблюдал дважды.
3. Динамические, тогда и количество элементов - переменная, и сами элементы - переменные.
4. Разреженные, тогда количество фактически хранимых элементов может быть меньше диапазона индексов.
5. Логические, каждый такой массив есть массив, номинально состоящий из всех элементов разреженного массива, количество элементов логического массива соответствует диапазону элементов разреженного массива. В принципе можно считать, что логический массив есть представление интерфейса разреженного массива.
6. Физические, это вообще не обязательно массивы, физический массив есть контейнер, содержащий все фактичеки хранимые элементы разреженного массива. Можно считать, что физический массив есть контейнер, на котором реализован разреженный массив, но без собственно реализации операций, отвечающих за разрежение. Физический массив может быть стаческим, или динамическим массивом, линейным или кольцевым списком (но не очередью, или стеком), массивом линейных или кольцевых списков (но не очередей, или стеков), деревом массивом деревьев, линейным или кольцевым списком (но не очередей, или стеков) деревьев деревом массивов, деревом линейных или кольцевых списков (но не очередей, или стеков) и много чем ещё, сколь угодно экзотическим. Но это обязательно контейнер и он обязательно допускает неразрушающее произвольное чтение элемента.
Очевидно, что разреженные и логические массивы явяются динамическими. Только константный массив целиком - константа, любой другой массив целиком - переменная. Но хотя массив - тоже переменная, но особая. В оличие от скалярных переменных, имеющих одно значение каждая, и струкутр, содержащих каэжая несколько переменных, чьи значения складываются в комплексное, но всёж одно значение всей структуры, массив вообще не имеет единого значения, весь массив имеет как раз только множество значений всех своих элементов и эти значения не складываются в нечто цельное. Это не сложная переменная, а перменная-контейнер. И термин "статический" в случае массива имеет иное значение, относящееся не к памяти, в которой он хранится, а к количеству элементов.

Это сообщение отредактировал(а) TarasProger - 14.8.2015, 09:48
PM MAIL   Вверх
TarasProger
Дата 14.8.2015, 09:59 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет



Цитата(ManiaK @  9.8.2005,  14:35 Найти цитируемый пост)
Итак, строение машин долгое время определяло их функции. Однако, за человеком давно замечена одна глупость: он всё пытается унифицировать. Иными словами, в один прекрасный день захотелось одному человеку объединить лопату и чайник в один предмет, причём так, чтобы можно было переключать их функциональность. Нажал кнопочку - чайник, нажал другую - лопата. Удобно!..

Так появились компьютеры. Да, это были, по сути своей, первые компьютеры. Устройство, которое следило за нажатием ваших кнопочек и переключением функций, фактически есть первая программа. Долго радовался человек на своё изобретение, однако и этому однажды пришёл конец. "Лучшее - враг хорошего" - говорят, и не зря...
Computer от английского to compute - вычислять. Значит вычислитель. А реагирование на кнопки - это ещё не вычисление, первый копьютер - это вообще арифмометр, второй - калькулятор.

PM MAIL   Вверх
TarasProger
Дата 14.8.2015, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет



Цитата(ManiaK @  9.8.2005,  14:35 Найти цитируемый пост)
Кстати, само разграничение понятий "процедура" и "функция" довольно условно и никто вас не имеет права щёлкнуть по носу, если вы вдруг употребить одно понятие взамен другого (хотя принято по возможности пользоваться вторым).
Процелура и функция различаются способом возврата значения. Если через имя самой подпрограммы - это функция, иначе - процедура. 
Код
val('3.14', a);
 - вызов процедуры, 
Код
a:=val('3.14');
 - вызов функции. Процедура может возращать значение через глобальную переменную, через модифицируемый параметр, через память, адрес которой передан в параметре-указтеле. Но её собственное имя не может быть указано идентификатором того опенда другого оператора, в котором ожидается результат работы процедуры. А имя функции в этом месте указать можно. На низком уровне нет функций, а есть только процедуры, просто некоторые из них умеют оставлять результаты своей работы в строго определённых местах согласно соглашению о вызовах. Это может быть регистр ax, вершина стека на момент сразу после возврата из функции, место в памяти сразу перед точкой входа в функцию, или что угодно ещё, прописанное в соглашении о вызовах, которым пользуется компилятор языка более высокого уровня. На высоком уровне могут быть и токо функции, как на c/c++, и только процедуры, и оба вида подпрограмм. На object pascal грань между ними вроде бы вообще стёрта: можно функцию вызвать как процедуру, возвращающую результата через первый параметр со стандартным именем Result. Если нет процедур, но есть функции, то вместо процедур в языке релаизованы фунции, формально возвращающие специциальные значения без данных. Если нет функций, но есть процедуры, то надо придётся, как на языке ассемблера, обходиться процедурами и изобретать способы возврата результатов их работы. Если поддерживаются оба вида подпрограмм, то и оба синтаксиса. Поэтому в зависимости от языка может быть принят любой из двух терминов, или все три.
PM MAIL   Вверх
TarasProger
Дата 14.8.2015, 14:37 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет



Цитата(Гость_ManiaK @  21.9.2005,  23:12 Найти цитируемый пост)
Насколько я понял из прочтения вашей статьи. Что указатель это переменная, которая содержит адрес другой переменой. Именно так.
Не всегда так. Во-первых указатель может содержать и адрес функции. А во-вторых указатель может быть и констатой. Указатель - это величина, содержащая адрес чего то другого. Это может быть:
1. Переменная, хранящая адрес другой переменной. Возможно другого указателя.
2. Константа, хранящая адрес переменной. Возможно другого указателя.
3. Переменная, хранящая адрес константы. Возможно другого указателя.
4. Константа, хранящая адерес другой константы. Возможно другого указателя.
5. Переменная, хранящая адрес функции.
6. Константа, хранящая адрес функции.
Указатель, хранящий адрес другого указателя, называется кратным указателем. Указатель, хранящий адерс другого указателя, в котором уже харнится адрес не указателья, называется двойным указателем. Указатель, хранящий адерс другого указателя, в котором опять хрантся адрес другого указателя, в котором уже харнится адрес не указателья, называется тройным указателем. Кратный - собирательное название. Кратность указателя - это количество указателей, включая данный, адреса которых нужны, чтоб по цепочке добраться до не указателя. Здесь: 
Код
int ****p;
 p - указатель на int кратности 4, то есть указатель на указатель на указатель на указатель на int.

Добавлено через 11 минут и 12 секунд
Цитата(Гость_ManiaK @  21.9.2005,  23:12 Найти цитируемый пост)
В ассемблерном коде (после компиляции) ссылок не существует. Это - абстракция, реально никакой памяти ссылки не занимают. Для чего они нужны? самый простой и в тоже время наиболее употребительный пример - передача объекта в функцию не копированием, а ссылкой (то есть передача самого объекта):
Вот как раз параметры ссылочных типов - это на самом деле такие константные указатели, которые не надо разыменовывать. Ни сайзоф, ни взятие адреса этого не покажут, так как настоящая, но временная и безымянная ссылка получается при разыменовании указателья, а параметр ссылочного типа при каждом использовании разыменуется по умолчанию. Но информацию о том, где переменная лежит, надо ведь как то в функцию передать и другого способа кроме указателя для этого на низком уровне нет.

Добавлено через 14 минут и 47 секунд
Цитата(maxim1000 @  22.9.2005,  00:56 Найти цитируемый пост)
ссылка ближе к указателю, чем к пременной
в общем-то именно так она и реализована на уровне компилятора
просто везде, где она используется, компилятор дорисовывает звездочку smile
Код
int x;
int &y=x;
y++;
x=y;
Эта ссылка ближе как раз к переменной, такая ссылка - это просто дублирующая запись с тем же адресом в таблице переменных компилятора. Ничего общего с указателем, хранящим адрес на этапе исполнения, она не имеет.

PM MAIL   Вверх
TarasProger
Дата 14.8.2015, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет



Цитата(ManiaK @  30.5.2006,  16:49 Найти цитируемый пост)
BlHol, абсолютно никакой разницы нет.  
Есть, причём, огромная. Декларация указателя и приведение к указательному типу.

Добавлено через 14 минут и 29 секунд
Цитата(ManiaK @  24.7.2006,  10:01 Найти цитируемый пост)
Да. Причём не обязательно другой переменной. У вас в программе может существовать указатель на память, которой не соответствует ни одна переменная. Каким образом мы получим доступ к этой памяти? Только с помощью указателя на неё. Это ответ на следующий вопрос:
Не путайте безымянные переменные с другими сущностями. 
Код
void f()
{
 int a[20];
 int *p;
 p=new int;// В этой строке значением p станованится адрес динимаческой безымянной переменной.
 delete p;
 p=&(a[5]);// В этой строке значением p станованится адрес безымянной переменной, но не динамической, а элемента другой именованной автоматической переменной.
}
. Переменная существует в обоих случаях, но у неё нет собственного имени. В одном случае переменная создана динамически и получить доступ к ней можно только по указателю, в другом безымеянна только конкретная переменная, но весь массив имеет имя, является обычной автоматической переменной и лежит на стеке, а доступ к её элементу можно получить двояко:
1. По указателю.
2. Вычислив адрес элемента по адерсу всего массива и индексу элемента.
Но если 
Код
 const double a=3.14;
 const double *p;
 p=&a;
, то по адресу в p нет переменной вообще. К величине по этому адресу можно получить доступ по имени самой величины, но ни какая переменная там не лежит, а лежит там константа. А в этом: 
Код
typedef void (*pf)(double);
int main ()
{
 pf p;
 p=f;
 случае p хранит адрес функции.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1330 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.