Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопросы по C от ламера
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
Скопидор
Зачем вообще нужно ключевое слово «auto»?
Ведь классификатор(или квалификатор? как это слово точно называется?) памяти «auto» никак не используется ( по крайней мере в исходниках разных разработчиков я его не видел).
Т.к. глобальные переменные не могут быть « auto», а локальные и так по умолчанию «auto».
mdmitry
The C++ Programming Language Special 3rd Edition Bjarne Stroustrup
Appendix C
C.9 Memory Management

Первоисточник, однако rolleyes.gif
SysRq
На Хабре было интересно: http://habrahabr.ru/blogs/cpp/25330/ (с подзаголовка "Ты где был, auto?").
Скопидор
Цитата(SysRq @ Apr 10 2009, 17:37) *
На Хабре было интересно: http://habrahabr.ru/blogs/cpp/25330/ (с подзаголовка "Ты где был, auto?").


" ... Спустя три десятка лет стандарт C++09 вновь вводит ключевое слово auto. Переменная, определённая под этим ключевым словом автоматически приобретёт тип при инциализации. ... "©
Обана! rolleyes.gif Ахринеть

А в книжках Павловской и Подбельского об этом использовании ключевого слова "auto" ни звука unsure.gif

P.S. Спасибо огромное за ответы, Господа mdmitry и SysRq.
Скопидор
Какие компиляторы (каких фирм) и начиная с какого года поддерживают ключевое слово "export" (т.е. экспорт шаблонов функций и классов)?

И есть ли Freeware компиляторы C++, с объёмом до 10МБ, которые ПОЛНОСТЬЮ поддерживают самый последний стандарт C++

Почему после того, как я вместо iostream.h стал юзать iostream объём экзешника вырос с 0.2МБ до почти о.5МБ?
andrew_b
Цитата(Скопидор @ Apr 11 2009, 02:02) *
Какие компиляторы (каких фирм) и начиная с какого года поддерживают ключевое слово "export" (т.е. экспорт шаблонов функций и классов)?

И есть ли Freeware компиляторы C++, с объёмом до 10МБ, которые ПОЛНОСТЬЮ поддерживают самый последний стандарт C++

Почему после того, как я вместо iostream.h стал юзать iostream объём экзешника вырос с 0.2МБ до почти о.5МБ?


Думаю, вам лучше обратиться на более специализированный ресурс. На RSDN, например. Для участия в профильных форумах там регистрироваться не обязательно.
Скопидор
Цитата(Student Pupkin @ Apr 13 2009, 23:15) *
Но я думал, что по общепринятым правилам следовало в одном из модулей обявить все эти глобальные переменные обычным образом, а в остальных - с квалификатором extern...

Дык объявлять каждую переменную в каждом из N модулей запарисся. Да и вероятность ошибки возрастает
................................................................................
.......





А Вы, BSVi, Сами себе противоречите.

С одной стороны Вы пишите:
Цитата(BSVi @ Apr 14 2009, 10:36) *
... внимание, в заголовках нельзя обьявлть переменные. кроме констант


А с другой пишите:

Цитата(BSVi @ Apr 14 2009, 10:36) *
... переменные .... лучше сделать отдельным модулем global_vars.c и global_vars.h

А разве global_vars.h - это не заголовочный файл?
ukpyr
Цитата
Дык объявлять каждую переменную в каждом из N модулей запарисся. Да и вероятность ошибки возрастает
правильно, в хидере каждого модуля обьявляются публичные переменные, видимые в других модулях. Подключаем .h файл - и получаем доступ к публичным переменным. А в .с файле модуля объявляются внутренние переменные модуля.
Скопидор
Цитата(ukpyr @ Apr 15 2009, 01:23) *
правильно, в хидере каждого модуля обьявляются публичные переменные, видимые в других модулях. Подключаем .h файл - и получаем доступ к публичным переменным. А в .с файле модуля объявляются внутренние переменные модуля.

А как из файла main_1.c я получу доступ к "публичным" переменным файла "main_2.h"?
Скопидор
1.А обязательно ли в препроцессорной директиве #include использовать файлы с расширением .h ? Т.е. могу ли, например, написать файл с раширением .my и вложить его содержимое в основной файл с помощью директивы #include?



2. Почему директиву #include используют в начале файла? А существуют ли случаи, когда выгодно использовать эту директиву в середине, или даже в конце основного файла? И что это за случаи?

3. Использование #include подразумевает экспортирование ресурсов из .h-файла. А бывают ли случаи, когда наоборот, вкладываемый файл импортирует ресурсы из того файла, в который он вкладывается? Если да, то что это за случаи?

Цитата(andrew_b @ Apr 13 2009, 09:32) *
Думаю, вам лучше обратиться на более специализированный ресурс. На RSDN, например.

Ссылка битая. Сайт не грузится


4.

Есть прога:

Код
void main(void)
{
     int I = 1;
     {    // блок2
          int I = 2;
          goto Exit;
          // ---------------
          I++;
     }
     I = 4;
     // ------------------
     Exit:;
     I = 3;
}
На входе в блок2, я так понимаю, компилятор сохранит в стеке регистровый контекст и выделит в стеке память под локальную переменную I. А на выходе компилятор должен будет восстановить контекст (в том числе указатель стека), который был непосредственно перед входом в блок2.
Но т.к. выполняется команда перехода за пределы блока2, то получается, что команды восстановления контекста из стека будут пропущены?





5.Если main – функция, то можно ли её рекурсивно вызвать внутри её самой?



6. Как избежать в своей программе непреднамеренного «экранирования» идентификаторов из стандартной библиотеки?
SysRq
Цитата(Скопидор @ Apr 11 2009, 02:02) *
Почему после того, как я вместо iostream.h стал юзать iostream объём экзешника вырос с 0.2МБ до почти о.5МБ?
wcin, wcout...

Цитата(Скопидор @ Apr 15 2009, 02:13) *
А обязательно ли в препроцессорной директиве #include использовать файлы с расширением .h ?
Нет. Часто применяется, к примеру, .hpp. Аналогия C -- .c, C++ -- .cpp.

Цитата(Скопидор @ Apr 15 2009, 02:13) *
...когда выгодно использовать эту директиву в середине, или даже в конце основного файла?
Когда выгодно! Скажем, изменить макрос какой-нить, используемый в исходнике, вставив .h-файл с ifdef-undef-define этого макроса в середину исходника, и пусть враги догадываются почему мой спёртый ими исходник у них не работает.

Цитата(Скопидор @ Apr 15 2009, 02:13) *
Использование #include подразумевает экспортирование ресурсов из .h-файла. А бывают ли случаи, когда наоборот...
Неверное понятие сути, нет там экспортирования никакого. Это паззл, если хотите smile.gif

Цитата(Скопидор @ Apr 15 2009, 02:13) *
Если main – функция, то можно ли её рекурсивно вызвать внутри её самой?
Зависит от того, как она определена, от атрибутов ее. Сохранение контекста и прочее...

Цитата(Скопидор @ Apr 15 2009, 02:13) *
Как избежать в своей программе непреднамеренного «экранирования» идентификаторов из стандартной библиотеки?
Читать документацию на используемые бибилиотеки.
Скопидор
Цитата(SysRq @ Apr 15 2009, 03:32) *
Неверное понятие сути, нет там экспортирования никакого. Это паззл, если хотите smile.gif

Ну как же. Например, я могу описать в h-файле прототип функции f1 и юзать его внутри тела функции f2, которая определена в h-файле. А вот конкретная реализация f1 будет содержаться в файле, в который будет вложен h-файл, т.е. как бы будет импортироваться из основного файла. Т.е. получается, что реализация f2 будет зависеть от того, куда будет вложен h-файл.


Цитата(SysRq @ Apr 15 2009, 03:32) *
Зависит от того, как она определена, от атрибутов ее. Сохранение контекста и прочее...

Т.е. в принципе возможно юзать вызовы main внутри тела main?


Цитата(SysRq @ Apr 15 2009, 03:32) *
Читать документацию на используемые бибилиотеки.

И больше никак? Т.е. я при выборе каждого идентификатора в своей проге должен смотреть: «а нет ли точно такого же идентификатора в стандартной библиотеке». Так?


А насчёт перепрыгивания участка восстановления контекста из стека что скажете?
SysRq
Цитата(Скопидор @ Apr 15 2009, 04:48) *
Ну как же.
Срочно читать как из .cpp получается .exe.

Цитата(Скопидор @ Apr 15 2009, 04:48) *
Т.е. в принципе возможно юзать вызовы main внутри тела main?
Можно. Поищите еще "точка входа".

Цитата(Скопидор @ Apr 15 2009, 04:48) *
Т.е. я при выборе каждого идентификатора в своей проге должен..
Вы какой язык изучать собрались? C++? Инкапсуляция, наследование, и т.п. -- туда читайте. Вопрос отпадет. О глобальных переменных флудить не будем, тема уже была, ищите на форуме.
Как правило хорошего тона afaik не следует использовать _такие и __такие вот идентификаторы в прикладной программе.

Цитата(Скопидор @ Apr 15 2009, 04:48) *
А насчёт перепрыгивания...
За goto - секирбашка. Особенно в C++. Флудить не будем, тема уже была тоже.
MrYuran
Цитата(Скопидор @ Apr 15 2009, 01:42) *
А как из файла main_1.c я получу доступ к "публичным" переменным файла "main_2.h"?

Код
/*
*  main_1.c
*/

#include main_2.h

...
MrYuran
Цитата(Скопидор @ Apr 15 2009, 02:13) *
Есть прога:
...
На входе в блок2, я так понимаю,
компилятор сохранит в стеке регистровый контекст
C чего бы это вдруг? 07.gif
Цитата
и выделит в стеке память под локальную переменную I. А на выходе компилятор должен будет восстановить контекст (в том числе указатель стека), который был непосредственно перед входом в блок2.
Никому он ничего не должен. Блок {} означает всего лишь составной оператор, никаких переходов и контекстов не имеется в виду.
andrew_b
Цитата(Скопидор @ Apr 15 2009, 02:13) *
1.А обязательно ли в препроцессорной директиве #include использовать файлы с расширением .h ? Т.е. могу ли, например, написать файл с раширением .my и вложить его содержимое в основной файл с помощью директивы #include?
Да. Расширение вообще ни причём. См. ниже.

Цитата
3. Использование #include подразумевает экспортирование ресурсов из .h-файла.
Ничего подобного. #include -- это просто включение текста одного файла в другой файл. Ничего больше. Почитайте про препроцессор.

Цитата
Ссылка битая. Сайт не грузится
Ссылка не битая. А сайт действительно не грузится. С ним это бывает крайне редко. Попробуйте попозже. Это лучший ресурс в рунете по программированию.
Скопидор
Цитата(andrew_b @ Apr 15 2009, 08:41) *
Ничего подобного. #include -- это просто включение текста одного файла в другой файл.

Да я в курсе. Просто я говорил о том, что можно код распределить по файлам так, что не CPP-файл будет юзать ресурсы из H-файла, а наоборот.
И это будет выглядеть как импортирование.

Приведу пример


CODE
// Файл f.h
int I,J;
int F1(int, int); // Прототип функции, реализация которой будет определена в C-файле
int F2(void); // Функция, которая использует F1
{
return (F1(I,J));
}


// Файл main1.c
#include "f.h "
int Result;
// --------------------
int F1( int A, B)
{
return (A*B)
}
// --------------------
void main (void)
{
I = 3;
J = 4;
Result = F2();
}
// --------------------


// Файл main2.c
#include "f.h "
int Result;
// --------------------
int F1( int A, B)
{
return (A+B)
}
// --------------------
void main (void)
{
I = 3;
J = 4;
Result = F2();
}
// --------------------


Вот и получается, что алгоритм работы определённой в файле f.h функции F2 зависит от того, в какой файл будет вложен f.h: в main1.c или в main2.c. Т.е. всё выглядит так, что как будто бы в функцию F1 импортируется реализация из C-файла, т.к. результат, возвращаемый функцией F1 (а значит и использующей её F2) зависит от того, в какой файл был вложен f.h.

Цитата(andrew_b @ Apr 15 2009, 08:41) *
Да. Расширение вообще ни причём. См. ниже.

А я вот когда работал в WinAVR, то там при создании проекта создаются категории Header и Source.

И если включить файл *.h в категорию Header, то можно даже в исходнике не писать #include *.h. Так как компилятор сам поймёт что *.h файл нужно вложить во все исходники проекта (во все *.c файлы).

Или я не прав?

Вот я и думаю, что если у меня файл, включнённый в категорию Header будет иметь расширение не h, а другое? "Подцепит" ли его компилятор автоматом к проекту?
MrYuran
Цитата(Скопидор @ Apr 15 2009, 11:30) *
И если включить файл *.h в категорию Header, то можно даже в исходнике не писать #include *.h. Так как компилятор сам поймёт что *.h файл нужно вложить во все исходники проекта (во все *.c файлы).

Хрень какую-то несёте в массы.
Компилятор не может ничего никуда автоматом "подцеплять".
Он может тупо компилить, что ему дадут.
Максимум что может быть, так это что ваши h-файлы будут видны из любого места проекта, и можно будет инклудить их просто #include "some_header.h"
без указания абсолютного пути.
Опять же, к компилятору это никаким боком, это делает утилита, формирующая makefile.
Скопидор
Цитата(SysRq @ Apr 15 2009, 05:45) *
Срочно читать как из .cpp получается .exe.

В 2 этапа: сначала по отдельности компилируем все файлы (получаем OBJ-файлы), потом линкуем. Правильно?



Цитата(SysRq @ Apr 15 2009, 05:45) *
Вы какой язык изучать собрались? C++? Инкапсуляция, наследование, и т.п. -- туда читайте. Вопрос отпадет. О глобальных переменных флудить не будем, тема уже была, ищите на форуме.

Т.е. если «очень постараться» ( smile.gif ) (ну не внимательно подойти к выбору идентификаторов в своей программе), то всё же есть вероятность «наступить на грабли» и случайно экранировать идентификаторы из стандартной библиотеки в своей проге? Я не говорю сейчас о своих идентификаторах, начинающихся на _, __ или заканчивающихся на _t.
Допустим, к примеру, я такой дуб, что не знал, что в библиотеке уже юзаются cin и cout. И взял, и переопределил их в своей проге. Может такое быть?


Цитата(SysRq @ Apr 15 2009, 05:45) *
За goto - секирбашка. Особенно в C++. Флудить не будем, тема уже была тоже.

Да я не собираюсь флудить, нужен или не нужен goto. Просто хотел узнать как это реализуется: осуществляется «прыжок» за пределы блока и при этом, КАК-ТО, восстанавливается контекст, сохранённый на входе в блок.

P.S. Прошу прощения, если мои вопросы кажутся глупыми, я ж говорю, я ламер.
ReAl
Цитата(Скопидор @ Apr 15 2009, 10:44) *
Допустим, к примеру, я такой дуб,
...
Может такое быть?
Запросто.
Но достаточно либо

определить свои cin/cout в своём пространстве имён oak и квалифицировать при использовании oak::cin

либо

не переносить сущности стандартной библиолтеки в глобальное пространство имён, что происходит при использовании
Код
#include <iostream.h>

вместо
Код
#include <iostream>

или при совсем глобальном переносе
Код
using namespace std;

В этом случае к "стандартно-библиотечным" придётся обращаться как к std::cin, но они тоже не пересекутся с новоявленными.

А вообще поломать можно что угодно.
Скопидор
Цитата(MrYuran @ Apr 15 2009, 11:41) *
Хрень какую-то несёте в массы.

Ну когда мы делаем "add File to Project" мы же хидеры добваляем в категорию "Header". И после того как файл проекта (dsn по-моему) сформирован, компилятор знает, какие *.h файлы юзать при сборке. Разве не так?

Цитата(MrYuran @ Apr 15 2009, 08:31) *
C чего бы это вдруг? 07.gif Никому он ничего не должен. Блок {} означает всего лишь составной оператор, никаких переходов и контекстов не имеется в виду.

А я прочитал в книшшке, что если внутри {…} определяются локальные переменные, то составной оператор автоматом становиться блоком со всеми вытекающими последствиями (сохранение контекста процессора при входе в блок, создание локальных переменных в стеке и т.п.)

Цитата(ReAl @ Apr 15 2009, 11:54) *
определить свои cin/cout в своём пространстве имён oak и квалифицировать при использовании oak::cin

А что такое «oak»?
….
Т.е. Ваше сообщение было к тому, что «сломать» очень сложно? Но ведь стандартная библиотека – это не только классы и шаблоны.
andrew_b
Цитата(ReAl @ Apr 15 2009, 11:54) *
Код
#include <iostream.h>
Так это давным-давно deprecated.

Цитата(Скопидор @ Apr 15 2009, 12:09) *
Ну когда мы делаем "add File to Project"
Ну и при чём тут компилятор.

Цитата
мы же хидеры добваляем в категорию "Header". И после того как файл проекта (dsn по-моему) сформирован, компилятор знает, какие *.h файлы юзать при сборке. Разве не так?
Компилятор про проект ничего не знает.
ReAl
Цитата(Скопидор @ Apr 15 2009, 10:47) *
Да я не собираюсь флудить, нужен или не нужен goto. Просто хотел узнать как это реализуется: осуществляется «прыжок» за пределы блока и при этом, КАК-ТО, восстанавливается контекст, сохранённый на входе в блок.
Обычно ничего никуда не сохраняется и не восстанавливается в таких блоках.
Код
voif foo()
{
    int i = 0;
    {
        char c;
        ...  
    }
    ++i;
    {
        long l;
        ...  
    }
    --i;
}
Компилятор анализирует всю функцию и в исполняемом коде уже на входе в функцию на стеке резервируется, грубо говоря
Код
struct {
    int i;
    union {
        char c;
        long l;
    };
} local_variables;
и больше стек туда-сюда не дёргается, просто происходит использование места на стеке в соответствии с деревом вложенных блоков кода. При минимальной современной оптимизации ещё и происходит анализ использования переменных и если какая-то используется до середины и дальше не нужна, а какая-то другая наоброт - используется только от середины (первое использование после последнего использования той), то они тоже накладываются в стеке для экономии его размера.
При этом переход по goto ничего не ломает (если он не обходит инициализацию переменной при попадании на метку, т.е. вопросы не к точке прыжка goto, а к точке приземления), так как структура/объединение на стеке остаются неподвижными, меняется только интерпретация.
Естественно, это так просто только для типов без конструкторов/деструкторов.
Особенно учитывая то, что во вложенных вызовах могут произойти исключения, которые подействуют "аналогично goto" с точки зрения этих объектов, а при отсутствии в данной функции try/catch её вообще всё "прошьёт". Поэтому для них в стековых кадрах функций устраиваются записи о деструкторах, которые необходимо выполнить при выходе из блока и порядке этих вызовов, при выходе из любого блока по goto/return/исключению просматриваются эти записи и вызываются необходимые деструкторы для автоматических объектов в блоках (unwind).
Код
#include <iostream>

class FOO
{
public:
    FOO(int i_) : i(i_) { std::cout << __PRETTY_FUNCTION__ << " (" << i << ")\n"; }
    ~FOO() { std::cout << __PRETTY_FUNCTION__ << " (" << i << ")\n"; }
private:
    int i;
};


int main(int ac, char **av)
{
    FOO f1(1);
    {
        FOO f2(2);
        if(ac == 1)
            goto aaa;
        // в случае перехода даже не сконструируется, но место на стеке под поле i зарезервировано заранее
        FOO f3(3);
    }
aaa:;
}

Вызываем с аргументом в командной строке (goto не выполняется)
Цитата
FOO::FOO(int) (1)
FOO::FOO(int) (2)
FOO::FOO(int) (3)
FOO::~FOO() (3)
FOO::~FOO() (2)
FOO::~FOO() (1)

Вызываем без аргумента
Цитата
FOO::FOO(int) (1)
FOO::FOO(int) (2)
FOO::~FOO() (2)
FOO::~FOO() (1)



Цитата(Скопидор @ Apr 15 2009, 11:09) *
А что такое «oak»?

http://www.abbyyonline.ru/Translate.aspx?l...1&words=oak
Можете для своих вещей выбрать другое имя. Можете несколько, для разных частей проекта свои.
Цитата(Скопидор @ Apr 15 2009, 11:09) *
Т.е. Ваше сообщение было к тому, что «сломать» очень сложно? Но ведь стандартная библиотека – это не только классы и шаблоны.
Оно к тому, что в языке есть средства для того, чтобы можно было не ломать.



Цитата(andrew_b @ Apr 15 2009, 11:19) *
Так это давным-давно deprecated.
У меня просто до сих пор в ходу mingw32-gcc 3.4.2 пятилетней давности, у него в backward/ ещё болтается всё smile.gif
Скопидор
Цитата(andrew_b @ Apr 15 2009, 12:19) *
Ну и при чём тут компилятор.
Компилятор про проект ничего не знает.

А для кого тогда создаётся DSN-файл?
.....................................
.....................................
.....................................
ReAl!!

Спасибо за столь развёрнутый и подробный ответ. Я его весь пока не асисилил, но работаю над этим smile.gif

Т.е. как я понял, компилятор выделяет память под все локальные переменные любого уровня вложенности блоков на входе в функцию? Т.е. если в функции описана переменная i, а во вложенном в функцию блоке – переменная j, то память в стеке и под i и под j будет выделена на входе в функцию, а уничтожена на выходе по команде return?
andrew_b
Цитата(Скопидор @ Apr 15 2009, 12:39) *
А для кого тогда создаётся DSN-файл?
Видимо, для IDE. IDE != компилятор.
Скопидор
Цитата(andrew_b @ Apr 15 2009, 13:11) *
Видимо, для IDE. IDE != компилятор.

Но ведь эта IDE позволяет не писать в каждом файле #include ..., т.е. берёт на себя функции компилятора?
mdmitry
IDE сама может при создании файла прописать некоторый код в него.
Для понимания ситуации возьмите голый компилятор (Вы с Winavr вроде работали) и соберите проект с помощью make, но makefile сделайте САМИ, а не из IDE взять (переписать).
Скопидор
Вопрос №7.

Можно ли использовать при объявлении (описании или определении) переменной использовать идентификатор типа, который будет опредёлён ниже или в другом файле? И как это сделать?

============================
Вопрос №8.

Вопрос по typedef.

Зачем писать так: typedef unsigned int UINT
Если можно так: #define UINT (unsigned int)

В чём принципиальная разница?


==================================
Вопрос №9.

Можно ли в C++ заставить компилятор АВТОМАТИЧЕСКИ генерировать код, контролирующий выход результатов вычислений за пределы допустимого диапазона? Есть ли для этого какие-то специальные ключи компиляции?

Допустим, есть такой фрагмент кода:

unsigned short int i , j , k ;

k = i + j // что будет если (i+j) > 65535?


============================
Вопрос №10.

Для чего нужно ключевое слово «signed» если оно никогда на практике не используется?


==============================
Вопрос №11.

Зачем нужны две формы инициализации переменной?

int i = 10 и int i(10)

В чём между ними принципиальная разница?
SysRq
Цитата(Скопидор @ Apr 15 2009, 19:42) *
...идентификатор типа, который будет опредёлён ниже или в другом файле?
Тип должен быть известен (прототип, или еще как-либо; declaration). Известным тип так же считается, если вы как раз его и описываете (простейший пример - свзяный список структур: в структуре при ее обявлении есть указатель на неё же).

Цитата(Скопидор @ Apr 15 2009, 19:42) *
Зачем писать так: typedef unsigned int UINT
Код
#define int_pointer int *
int_pointer myint1, myint2;
После подстановки препроцессором:
Код
int *myint1, myint2; // первое - указатель, а второе-то вовсе нет; а с typedef все будет правильно

Цитата(Скопидор @ Apr 15 2009, 19:42) *
...АВТОМАТИЧЕСКИ генерировать код, контролирующий выход результатов вычислений за пределы допустимого диапазона?
k = i + j // что будет если (i+j) > 65535?
Хороший компилятор выдаст предупреждение о возможном переполнении.
Будет отброшено то что не влезает, старшие биты.

Цитата(Скопидор @ Apr 15 2009, 19:42) *
Для чего нужно ключевое слово «signed» если оно никогда на практике не используется?
По-умолчанию char в WinAVR (и не только) считается unsigned (опция компилятора). Использовать signed - единственный способ заставить его в таком случае работать как со знаковой.

Цитата(Скопидор @ Apr 15 2009, 19:42) *
int i = 10 и int i(10)
Присваивание значения либо через оператор =, или через конструктор.
Скопидор
Цитата(SysRq @ Apr 16 2009, 00:00) *
Присваивание значения либо через оператор =, или через конструктор.

А когда лучше какую из форм юзать?

P.S. И ещё. Насколько я понял форму инициализации со скобками можно юзать только для локальных переменных. Почему?
demiurg_spb
Цитата(Скопидор @ Apr 16 2009, 00:34) *
А когда лучше какую из форм юзать?
Через конструктор с аргументом. Т.к произойдёт создание переменной с одновременной инициализацией,
а в другом случае будет два хода, создание переменной со значением по умолчанию (если оно есть) и только потом присвоение ей значения через оператор =, который реализуется обычно посредством конструктора копирования.
Даже наверное хуже: создание переменной со значением по умолчанию, создание переменной с желаемым значением копирование одного в другое, удаление временной переменной...
Писать на С++ можно начинать предварительно прочитав несколько штук весьма занимательных книжекsmile.gif
Помимо Бьёрна Страуструпа, очень рекомендую эти две книжечки: Скотт Майерс Эффективное использование С++ 50 способов и вторая часть 35 способов:
http://www.bookvoed.ru/searching_for_shop276755.html
Я читал и плакалsmile.gif
andrew_b
Цитата(Скопидор @ Apr 15 2009, 19:42) *
Вопрос №10.
Для чего нужно ключевое слово «signed» если оно никогда на практике не используется?
Не надо обощать. Если вы его не используете, то это не значит, что другие не используют тоже. Как быть с отрицательными числами?

Цитата(SysRq @ Apr 16 2009, 00:00) *
Тип должен быть известен (прототип, или еще как-либо; declaration). Известным тип так же считается, если вы как раз его и описываете (простейший пример - свзяный список структур: в структуре при ее обявлении есть указатель на неё же).
Ну, это всё-таки указатель, а не сама структура. Размер указателя всегда известен. А размер структуры -- только после того, как она будет полностью описана. Нпример, вы не можете написать:
Код
struct foo;

struct bar
{
     struct foo;
};
_Pasha
Цитата(Скопидор @ Apr 15 2009, 18:42) *
Вопрос №10.
Для чего нужно ключевое слово «signed» если оно никогда на практике не используется?

Хороший пример:
Код
typedef signed char int8_t;

Но знаковость char по умолчанию можно задать еще и в командной строке! Ясное дело, отдавать себя на откуп памаметрам ком строки никто не согласится.
Скопидор
Возвращаясь к обсуждению директивы #include.

В некоторых книжках (вроде даже сам Страусс) пишут, что «единицей компиляции» является файл и что программа на C++ может состоять из нескольких файлов-исходников и что имеет место быть «раздельная компиляция». Т.е. файлы компилируются по отдельности и получается несколько OBJ-файлов, а затем эти «объектники» линкуются в один экзешник.

А если исходить из идеологии «include», то получается, что сначала препроцессор собирает из нескольких исходников один единственный исходник, и это ОДИН (!!!) файл компилируется.

Поясните мне это противоречие.

А потом, когда мы пишем, к примеру, #include <iostream> ведь не вставляется же сам исходный текст системного библиотечного файла в файл юзверя? Поскольку этого исходного текста нет в дистрибутиве (особенно если компилятор коммерческий), а есть его некий объектный код. Так?

Или я не прав?

Т.е. объясните мне как компилятор узнаёт когда нужно вставить текст в исходник, а когда нужно присоединить объектник файла уже на фазе линковки
andrew_b
Цитата(Скопидор @ Apr 23 2009, 15:28) *
Поясните мне это противоречие.
Нет противоречия. Компилируется результат препроцессинга. А это один файл.

Цитата
А потом, когда мы пишем, к примеру, #include <iostream> ведь не вставляется же сам исходный текст системного библиотечного файла в файл юзверя? Поскольку этого исходного текста нет в дистрибутиве (особенно если компилятор коммерческий), а есть его некий объектный код. Так?
Вы бы что ли ради интереса в этот файл заглянули.

Цитата(Скопидор @ Apr 23 2009, 16:22) *
Т.е. объясните мне как компилятор узнаёт когда нужно вставить текст в исходник, а когда нужно присоединить объектник файла уже на фазе линковки
Препроцессор, компилятор и линкер -- это разные программы.
MrYuran
Ещё раз.

Встретив директиву #include "filename.x", препроцессор ТУПО подставляет на это место содержимое соответствующего файла.
И его в общем-то не интересует, что в том файле. С этим дальше будет разбираться компилятор.

Далее полученный модуль компилируется в объектник.

Так что никаких противоречий.

Если имя файла в угловых скобках <>, это всего лишь означает, что он будет сначала искаться в системных директориях компилятора, а затем уже в файлах проекта.

Код из библиотек не подставляется при компиляции, а линкуется при конечной сборке.
Скопидор
Дык всё-таки "раздельная компиляция" есть такое понятие? Или это всё домыслы манагеров и что реально компилиться всегда один CPP-исходник?
andrew_b
Цитата(Скопидор @ Apr 23 2009, 16:29) *
Дык всё-таки "раздельная компиляция" есть такое понятие?
Да, есть.
Цитата
реально компилится всегда один CPP-исходник?
Да.
Скопидор
Цитата(MrYuran @ Apr 23 2009, 16:27) *
Код из библиотек не подставляется при компиляции, а линкуется при конечной сборке.

А мне сказали, что препроцессор - это отдельная прога. Откуда она знает какой файл из библиотеки, а какой нет? unsure.gif
MrYuran
Цитата(Скопидор @ Apr 23 2009, 16:29) *
Дык всё-таки "раздельная компиляция" есть такое понятие? Или это всё домыслы манагеров и что реально компилиться всегда один CPP-исходник?

Ну если он один, то да.
Если два - то сначала один, потом другой.
Если три - то сначала один, потом второй, потом третий.
И т.д.

И всё это в соответствии с makefile -ом или опциями командной строки
Скопидор
Т.е. препроцессор каким-то чудесным образом узнаёт в каких случаях при встрече им директивы #include вставлять вместо #include содержимое файла, а когда нет?

А если он не вставляет содержимое системного файла в наш исходник, то почему компилятор не ругается "undefined variable" если мы юзаем переменные из системного файла?



Цитата(MrYuran @ Apr 23 2009, 16:27) *
Код из библиотек не подставляется при компиляции

А тогда зачем вообще писать, к примеру, #include <iostream> если препроцессор всё равно не подставляет код из этого библиотечного файла в наш исходник?
AndreyKeil
Цитата(Скопидор @ Apr 23 2009, 18:35) *
А мне сказали, что препроцессор - это отдельная прога. Откуда она знает какой файл из библиотеки, а какой нет? unsure.gif

Где какой файл он узнаёт из путей, которые ему указывают. Если это кавычки (двойные или одинарные,не помню),то ищется в текущей директории проекта. Если угловые скобки, то в директориях, где сидят библиотеки, компиляторы, линкеры, т.е. иначе - системные директории. Пути прописываются в настройках компилятора, линкера, или препроцессора, или в среде разработки, смотря в чём вы работаете.
Скопидор
Цитата(AndreyKeil @ Apr 23 2009, 16:54) *
Где какой файл он узнаёт из путей, которые ему указывают. Если это кавычки (двойные или одинарные,не помню),то ищется в текущей директории проекта. Если угловые скобки, то в директориях, где сидят библиотеки, компиляторы, линкеры, т.е. иначе - системные директории. Пути прописываются в настройках компилятора, линкера, или препроцессора, или в среде разработки, смотря в чём вы работаете.

Т.е. работа препроцессора (вставлять содержимое файла в наш файл или не вставлять) зависит от того, в какой директории находится файл указанный в #include?
mdmitry
Цитата(Скопидор @ Apr 23 2009, 17:03) *
Т.е. работа препроцессора (вставлять содержимое файла в наш файл или не вставлять) зависит от того, в какой директории находится файл указанный в #include?


Вставлять всегда, а искать этот файл сначала в зависимости от скобок. <> ищется сначала в системных файлах, затем в тех каталогах, которые указаны в настойках, включая каталог проекта.

А чего рассуждать. Берете свой проект, в какой-то исходный файл пишите #include на несуществующий. Далее компиляция и разбор полетов. Очень наглядно rolleyes.gif

Использование препроцессора позволяет часто найти свои ошибки в #define.

P.S. Может документацию по используемому Вами компилятору почитать, да и в книгах по С, CPP обычно использование препроцессора, компилятора, линкера и библиотекаря разбирается.
Скопидор
Вопрос №12
Как и для чего в C++ используется идентификатор типа в enum кроме объявления/определения переменных?

Код
// main.cpp
// 18:17 23 апреля 2009 г.
#include <iostream>
using namespace std;
void main ()
{
    enum My_Type {null, one, two, three};
    My_Type A;
    A = My_Type (10);              // Почему здесь компилятор не ругается? Ведь 10 не входит в множество значений типа My_Type
    cout << "A = " << A << '\n';   // Пишет A = 10, хотя 10 больше самой большой из констант описанных в enum типа My_Type
}



///////////////////////////////////////////////////
///////////////////////////////////////////////////

Цитата(mdmitry @ Apr 23 2009, 17:21) *
Вставлять всегда


??? cranky.gif

А как же такие понятия как "раздельная компиляция" и "предкомпилированные файлы библиотек"?

А как же высказывания участника:
Цитата(MrYuran @ Apr 23 2009, 16:27) *
Код из библиотек не подставляется при компиляции, а линкуется при конечной сборке.





///////////////////////////////////////////////////
///////////////////////////////////////////////////


Вопрос №13 (Про функцию main)

В книгах по C++ вначале пишут что выполнение программы начинается с функции main. Но в главах, посвящённых классам, пишут что выполнение программы начинается с выполнения конструкторов объектов глобальных классов. Так с чего же всё-таки начинается выполнения программы?


//////////////////////////////////////////////////////////

Вопрос №14

В книгах по C++ пишут, что в строковых литералах допустимы почти любые символы. А какие символы не допустимо использовать внутри строкового литерала?


Замечание модератора. Скопидор, Вы начинаете злоупотреблять возможностями по форматированию текста сообщения, нарушая п.2.1г Правил форума.
MrYuran
Цитата(Скопидор @ Apr 23 2009, 16:51) *
А если он не вставляет содержимое системного файла в наш исходник, то почему компилятор не ругается "undefined variable" если мы юзаем переменные из системного файла?
А тогда зачем вообще писать, к примеру, #include <iostream> если препроцессор всё равно не подставляет код из этого библиотечного файла в наш исходник?

В h-файлах обычно определяются константы, макросы, предварительные объявления функций и ссылки на переменные.

То есть, если вы используете в тексте переменные или функции из других модулей, то они должны быть объявлены до использования.
Переменные - как extern, функции - как предварительное описание.

Например, встретив в тексте описание
viod SomeFunc();
компилятор будет спокойно воспринимать вызовы этой функции, подразумевая, что она более подробно описана в другом месте (в другом модуле, библиотеке, а может быть, в текущем, но ниже)
Скопидор
Цитата(MrYuran @ Apr 23 2009, 19:09) *
В h-файлах обычно определяются константы, макросы, предварительные объявления функций и ссылки на переменные.

Да какая разница что там описано в этих h-файлах (а, кстати, где Вы увидели h в приведённой мной выше строке #include <iostream> ?) если Вы сами же пишите:
Цитата(MrYuran @ Apr 23 2009, 16:27) *
Код из библиотек не подставляется при компиляции, а линкуется при конечной сборке.

Из чего следует, что содержимое этих "h-файлов"не добавляется препроцессором в наш исходник
sergeeff
Все что имеется в h-файлах и не отключается командами препроцессора типа #if, #ifdef включается в исходник и далее компилируется. Что вам в этом процессе не понятно?

Вам надо разобраться с книгой в руках, что такое объявление переменных, функций, классов, и что такое их определение. Например, здесь можно почитатъ : http://it-library.org/articles/?c=6&&a=139.

Каша у вас в голове на сегодняшний день. "Любите книгу - источник знаний"
MrYuran
Цитата(Скопидор @ Apr 23 2009, 19:18) *
Из чего следует, что содержимое этих "h-файлов"не добавляется препроцессором в наш исходник

содержимое "этих h-файлов" используется компилятором для формирования ссылок на внешние переменные и функции, которые затем цепляются линкером.
При этом в объектный код компилируемого модуля никакой дополнительный код из внешних модулей не вставляется.

Короче, учите матчасть. Лучше всего взять конкретный исходник (желательно грамотно написанный) и разобрать его по косточкам.
Скопидор
Цитата(sergeeff @ Apr 23 2009, 19:38) *
Вам надо разобраться с книгой в руках....
Каша у вас в голове на сегодняшний день. "Любите книгу - источник знаний"

Цитата(MrYuran @ Apr 23 2009, 20:57) *
Короче, учите матчасть.


"P.S. Модераторы и гуру, вы реально помогайте людям кто вообще не в теме, ведб вы когда-то тоже были лохами в программинге, и вас когда-то тоже пинали, мол зелень читай больше книжки. Ведь неприятно? Люди не просят книг, а просят реальной помощи"©-Цитата(Denis89 @ Apr 10 2009, 23:56)





////////////////////////////////////////////


Цитата(sergeeff @ Apr 23 2009, 19:38) *
Все что имеется в h-файлах и не отключается командами препроцессора типа #if, #ifdef включается в исходник и далее компилируется. Что вам в этом процессе не понятно?


Непонятно вот это:

Цитата(MrYuran @ Apr 23 2009, 16:27) *
Код из библиотек не подставляется при компиляции, а линкуется при конечной сборке.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.