реклама на сайте
подробности

 
 
6 страниц V  < 1 2 3 4 > »   
Closed TopicStart new topic
> Вопросы по C от ламера, В книжках ответа чёта не нахожу
andrew_b
сообщение Apr 15 2009, 04:41
Сообщение #16


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Скопидор @ Apr 15 2009, 02:13) *
1.А обязательно ли в препроцессорной директиве #include использовать файлы с расширением .h ? Т.е. могу ли, например, написать файл с раширением .my и вложить его содержимое в основной файл с помощью директивы #include?
Да. Расширение вообще ни причём. См. ниже.

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

Цитата
Ссылка битая. Сайт не грузится
Ссылка не битая. А сайт действительно не грузится. С ним это бывает крайне редко. Попробуйте попозже. Это лучший ресурс в рунете по программированию.
Go to the top of the page
 
+Quote Post
Guest_Скопидор_*
сообщение Apr 15 2009, 07:30
Сообщение #17





Guests






Цитата(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, а другое? "Подцепит" ли его компилятор автоматом к проекту?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Apr 15 2009, 07:41
Сообщение #18


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



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

Хрень какую-то несёте в массы.
Компилятор не может ничего никуда автоматом "подцеплять".
Он может тупо компилить, что ему дадут.
Максимум что может быть, так это что ваши h-файлы будут видны из любого места проекта, и можно будет инклудить их просто #include "some_header.h"
без указания абсолютного пути.
Опять же, к компилятору это никаким боком, это делает утилита, формирующая makefile.
Причина редактирования: Излишнее цитирование.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Guest_Скопидор_*
сообщение Apr 15 2009, 07:47
Сообщение #19





Guests






Цитата(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. Прошу прощения, если мои вопросы кажутся глупыми, я ж говорю, я ламер.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 15 2009, 07:54
Сообщение #20


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



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

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

либо

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

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

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

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

А вообще поломать можно что угодно.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Guest_Скопидор_*
сообщение Apr 15 2009, 08:09
Сообщение #21





Guests






Цитата(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»?
….
Т.е. Ваше сообщение было к тому, что «сломать» очень сложно? Но ведь стандартная библиотека – это не только классы и шаблоны.
Причина редактирования: Излишнее цитирование.
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Apr 15 2009, 08:19
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(ReAl @ Apr 15 2009, 11:54) *
Код
#include <iostream.h>
Так это давным-давно deprecated.

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

Цитата
мы же хидеры добваляем в категорию "Header". И после того как файл проекта (dsn по-моему) сформирован, компилятор знает, какие *.h файлы юзать при сборке. Разве не так?
Компилятор про проект ничего не знает.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 15 2009, 08:30
Сообщение #23


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Скопидор @ 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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Guest_Скопидор_*
сообщение Apr 15 2009, 08:39
Сообщение #24





Guests






Цитата(andrew_b @ Apr 15 2009, 12:19) *
Ну и при чём тут компилятор.
Компилятор про проект ничего не знает.

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

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

Т.е. как я понял, компилятор выделяет память под все локальные переменные любого уровня вложенности блоков на входе в функцию? Т.е. если в функции описана переменная i, а во вложенном в функцию блоке – переменная j, то память в стеке и под i и под j будет выделена на входе в функцию, а уничтожена на выходе по команде return?

Сообщение отредактировал Скопидор - Apr 15 2009, 08:42
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Apr 15 2009, 09:11
Сообщение #25


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Скопидор @ Apr 15 2009, 12:39) *
А для кого тогда создаётся DSN-файл?
Видимо, для IDE. IDE != компилятор.
Go to the top of the page
 
+Quote Post
Guest_Скопидор_*
сообщение Apr 15 2009, 10:09
Сообщение #26





Guests






Цитата(andrew_b @ Apr 15 2009, 13:11) *
Видимо, для IDE. IDE != компилятор.

Но ведь эта IDE позволяет не писать в каждом файле #include ..., т.е. берёт на себя функции компилятора?
Go to the top of the page
 
+Quote Post
mdmitry
сообщение Apr 15 2009, 11:56
Сообщение #27


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



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


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
Guest_Скопидор_*
сообщение Apr 15 2009, 15:42
Сообщение #28





Guests






Вопрос №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)

В чём между ними принципиальная разница?

Сообщение отредактировал Скопидор - Apr 15 2009, 15:44
Go to the top of the page
 
+Quote Post
SysRq
сообщение Apr 15 2009, 20:00
Сообщение #29


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(Скопидор @ 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)
Присваивание значения либо через оператор =, или через конструктор.
Go to the top of the page
 
+Quote Post
Guest_Скопидор_*
сообщение Apr 15 2009, 20:34
Сообщение #30





Guests






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

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

P.S. И ещё. Насколько я понял форму инициализации со скобками можно юзать только для локальных переменных. Почему?
Причина редактирования: Нарушение п.3.4 Правил форума.
Go to the top of the page
 
+Quote Post

6 страниц V  < 1 2 3 4 > » 
Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 23:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01536 секунд с 7
ELECTRONIX ©2004-2016