Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Исходные файлы с описанием класса


Автор: efpies 18.1.2011, 16:23
Здравствуйте.
Очень ламерский вопрос, на самом деле.

У меня в проекте несколько классов. Как было бы правильно их разбивать по файлам? Каждый класс в отдельный cpp-файл? Или в h-файл? Или в h-файле - прототипы и константы, а в cpp, который подключён к h, - описание? Как правильно?

Автор: KaraKum 18.1.2011, 16:32
Некоторые фанатики каждый класс описывают в отдельном .h-файле (называя файл так же как и класс но только маленькими буквами и разделяя слова пробелами - получается ужасно).
Можно делить объявления классов по логическим признакам. Например классы отвечающие за графику - в одном файле; за логику - в другом. Общих нареканий в этой области нет (в отличии от, например, по оформлению кода (самая известная - GNU-style)).
Код определения функций можно писать прямо в объявлении этих функций (в .h-файле) если подразумевается что файл будет подключаться к проекту только в одном месте (что как раз это подчёркивает)
Не забывать что можно писать и "#include "definition.cpp"" - то есть вообще обойтись без header'ов  smile

Добавлено через 3 минуты и 43 секунды
В остальном могут быть только какие-то частные нарекания. Например какие-то глобальные переменные (как же без них) можно определить в "globals.cpp":
Код

namespace Globals
{
     int someGlobalVariable = 0;
     ClassName *someGlobalClassInstance = new ClassName;
}//namespace Globals

И создать вот такой "externs.h", который можно подключать в любом другом файле где нужно использовать глобальные переменные:
Код

#ifndef EXTERNS_H
#define EXTERNS_H

namespace Globals
{
     extern int someGlobalVariable;
     extern ClassName *someGlobalClassInstance;
}//namespace Globals

#endif//#ifndef EXTERNS_H


Добавлено через 9 минут и 21 секунду
Вообще, все эти проблемы решаются как сами собой разумеющиеся после должного проектирования программы (перед её написанием или в процессе). Для этого можно пользоваться средствами http://ru.wikipedia.org/wiki/Объектно-ориентированное_программирование, http://ru.wikipedia.org/wiki/Разработка_через_тестирование и общие принципы проектирования рисованием http://www.graphviz.org/, http://ru.wikipedia.org/wiki/UML-диаграмм...

Автор: mes 18.1.2011, 17:08
Цитата(KaraKum @  18.1.2011,  15:32 Найти цитируемый пост)
Не забывать что можно писать и "#include "definition.cpp"" - то есть вообще обойтись без header'ов  

и нажить проблем smile

Автор: KaraKum 18.1.2011, 17:08
Цитата(mes @ 18.1.2011,  18:08)
Цитата(KaraKum @  18.1.2011,  15:32 Найти цитируемый пост)
Не забывать что можно писать и "#include "definition.cpp"" - то есть вообще обойтись без header'ов  

и нажить проблем smile

Именно.

Автор: mes 18.1.2011, 17:09
Цитата(KaraKum @  18.1.2011,  15:32 Найти цитируемый пост)
Некоторые фанатики каждый класс описывают в отдельном .h-файле

далеко не только фанатики... 

Автор: KaraKum 18.1.2011, 19:41
Цитата(mes @ 18.1.2011,  18:09)
Цитата(KaraKum @  18.1.2011,  15:32 Найти цитируемый пост)
Некоторые фанатики каждый класс описывают в отдельном .h-файле

далеко не только фанатики фанатики...

Скорее-всего я неясно высказался.
Иногда бывает что какие-то структуры используются только внутри какой-то одной функции - такие структуры вполне логично объявлять внутри самой этой функции, однако некоторые ФАНАТИКИ выделят для этой структуры отдельный файл, назвав этот файл в её честь.  smile 

Автор: borisbn 18.1.2011, 21:06
2 TS:  пишу с КПК в автобусе, поэтому коротко: KaraKum дал тебе ОЧЕНЬ плохие советы. Что про несколько классов в одном h-нике, что инклюд срр-шника, что про глобальные переменные. Чуть позже подробнее отпишусь 

Автор: KaraKum 18.1.2011, 22:42
Опаньки  smile 
Ну вот - TS в чрезвычайном режиме спасли от моих смертельных советов  smile

Добавлено через 55 секунд
Кстати, инклудить .cpp-файлы я не советовал - сказал лишь что это возможно. А вот объявление нескольких классов в одном хедере и глобальные переменные - это советовал (описал как это делать).

Автор: borisbn 19.1.2011, 10:43
Цитата(KaraKum @  18.1.2011,  22:42 Найти цитируемый пост)
не советовал - сказал лишь что это возможно

у новичков часто строится такая цепочка "возможно-так можно делать-так делают-так делают все-так нужно делать". Возможно ещё создавать функции на 2000 строк, делать такие конструкции ( пару лет назад достался проект по наследству, так я этот кусок сохранил, чтобы показывать как не надо делать )
Код

// Построение гистограммы
Histogramm[szMin - MIN_LEVEL + int(*pMP++)]++;

и т.п., однако сообщать новичкам, что это всё возможно IMHO не стОит.
Теперь о нескольких классах в одном хедере. Если класс настолько маленький и простенький, что для него не нужен отдельный файл, то его и создавать не нужно, скорее всего можно обойтись "свободными" функциями ( исключения составляют лишь функторы, но с приходом стандарта 0x00 и в них не будет особой необходимости ). Если же класс сложнее, чем пару функций get/set и если он создан для того, чтобы повторно его использовать ( и не в одном проекте, а в многих последующих ), то его просто необходимо вынести в отдельный файл. Так ведь даже удобнее.
А глобальные переменные ( не константы ) - вообще зло, т.к. сегодня тебе хватает производительности, а завтра - нет, и приходится распараллеливать программу, делать несколько потоков... далее, думаю, понятно.

P.S. Кажется TS уже забыл о нас, и всё это превращается во флуд. Предлагаю засим закончить smile

Автор: efpies 19.1.2011, 11:09
TS мониторит тему потихоньку)
Спасибо за советы.

Почему у меня возник такой вопрос: вот пишут, что
Цитата

Заголовочный файл в общем случае может содержать любые конструкции языка программирования, но на практике исполняемый код (за исключением inline-функций в C++) в заголовочные файлы не помещают.


Ну хорошо, сейчас у меня каждый класс в отдельном h-файле (каждый строк на 200, потому всё в один файл пихать - это будет кровавое месиво, тем более каждый класс считай как модуль), который имеет имя такое, как класс. Насколько это верно с учётом этой цитаты?) Да и вообще при каком-либо изменении какого-либо класса нужно сначала сделать build, а только потом run (видимо, сказывается специфика h-файлов), что сказывается на отладке не лучшим образом. Вот мне и подумалось, а не в cpp-файлы ли помещать их описание и т.д.? Ну и соответственно, что будет являться "хорошим стилем".

Автор: borisbn 19.1.2011, 11:54
efpies, самая общепринятая практика следующая: в h-файлах класс описывается, а в cpp-файлах - определяется. Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора, причём только тем, кто его создаёт. При этом, если ты изменяешь договор между разработчиком класса и его потребителем, то тебе необходимо перекомпилировать и сам класс, и те исходники, которые его используют. Если же ты меняешь только ход исполнения договора, при этом контракт остаётся нетронутым, то достаточно только перекомпилировать исходник класса. А вообще без перекомпиляции при изменении в Си/Си++ никак. Это не скриптовый язык.
Вот пример нормальной организации класса и его использования:
SomeClass.h
Код

#if !defined( _SOME_CLASS_H_INCLUDED_ )
#define _SOME_CLASS_H_INCLUDED_ 

class SomeClass {
public:
  SomeClass();
  ~SomeClass();
  void foo();
private:
  int m_x;

  void bar();
};
#endif //!defined( _SOME_CLASS_H_INCLUDED_ )


SomeClass.cpp
Код

#include "SomeClass.h"

SomeClass::SomeClass()
  : m_x( 0 )
{
}

SomeClass::~SomeClass() {
}

void SomeClass::foo() {
}

void SomeClass::bar() {
}


SomeClassUsing.h (использование SomeClass)
Код

#if !defined( _SOME_CLASS_USING_H_INCLUDED_ )
#define _SOME_CLASS_USING_H_INCLUDED_ 

class SomeClass;

class SomeClassUsing {
public:
  SomeClassUsing();
  ~SomeClassUsing();
private:
  SomeClass * m_someClass;
};
#endif //!defined( _SOME_CLASS_USING_H_INCLUDED_ )


SomeClassUsing.cpp (использование SomeClass)
Код

#include "SomeClassUsing.h"
#include "SomeClass.h"

SomeClassUsing::SomeClassUsing() {
  m_someClass = new SomeClass();
}

SomeClassUsing::~SomeClassUsing() {
  delete m_someClass;
}


Автор: KaraKum 19.1.2011, 13:13
http://www.fcenter.ru/forprint.shtml?online/articles/software/interview/7963 рисованные карандашом картинки могут быть интересны.

Автор: efpies 19.1.2011, 21:30
borisbn, KaraKum, спасибо за наглядные ответы! smile


Цитата(borisbn @  19.1.2011,  11:54 Найти цитируемый пост)
А вообще без перекомпиляции при изменении в Си/Си++ никак. Это не скриптовый язык.

Это понятно, просто либо компилятор сам перекомилирует, либо я это делаю насильно. Это я имел в виду.

Возник такой вопрос: к примеру, у меня есть 2 h-файла и 2 соответствующих cpp-файла (то есть, как Вы описали). Что в конечном итоге включается в использующий файл? Ну я имею в виду, что если мы включим в main.cpp SomeClassUsing.h, он же не будет знать о существовании SomeClassUsing.cpp, поскольку в заголовочном файле он никак не затрагивается. Или компилятор будет знать "по умолчанию" о существовании cpp-файла, поскольку имена одинаковые?

Автор: KaraKum 19.1.2011, 22:59
Я уже даже боюсь отвечать, ато теперь не из автобуса "по рации" сообщат о некомпетентности, а в квартиру постучат и конвоируют  smile 

"Превращение исходного кода в исполняемый" выполняется в два этапа: компиляция и, затем, компоновка (есть ещё препроцессор, но его относят к компиляции).
В процессе компиляции формируется никак не связанный набор функций (в том числе и main()). Процесс компиляции в местах вызовов функций лишь проверяет факт их описания (существования) и, конечно, вызываемые параметры. При компоновке на места вызовов функций располагаются уже настоящие адреса расположения этих функций (их исполняемые варианты, созданные в процессе компиляции) - если компоновщик не находит какую-либо скомпилированную функцию, то будет ругаться и откажется компилировать.
Поэтому если не указать .cpp файлов, то процесс компиляции может завершиться успешно, но компоновка нет.

Автор: mes 19.1.2011, 23:06
Цитата(efpies @  19.1.2011,  20:30 Найти цитируемый пост)
. Или компилятор будет знать "по умолчанию" о существовании cpp-файла, поскольку имена одинаковые? 

каждый .cpp файл компилится отдельно, но вместе со всеми включениями..
для того чтоб знать какие вы файлы хотите скомпилить и с чем их собрать используют make-файл..
IDE позволяет использовать его неявно для пользователя.. 



Автор: KuMa1104 20.1.2011, 00:57
Всем здрасте)))
 
Цитата(borisbn @  19.1.2011,  11:54 Найти цитируемый пост)
efpies, самая общепринятая практика следующая: в h-файлах класс описывается, а в cpp-файлах - определяется. Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора, причём только тем, кто его создаёт. При этом, если ты изменяешь договор между разработчиком класса и его потребителем, то тебе необходимо перекомпилировать и сам класс, и те исходники, которые его используют. Если же ты меняешь только ход исполнения договора, при этом контракт остаётся нетронутым, то достаточно только перекомпилировать исходник класса. А вообще без перекомпиляции при изменении в Си/Си++ никак. Это не скриптовый язык.
Вот пример нормальной организации класса и его использования:
SomeClass.h
код C++
#if !defined( _SOME_CLASS_H_INCLUDED_ )
#define _SOME_CLASS_H_INCLUDED_ 
class SomeClass {
public:
  SomeClass();
  ~SomeClass();
  void foo();
private:
  int m_x;
  void bar();
};
#endif //!defined( _SOME_CLASS_H_INCLUDED_ )


SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass()
  : m_x( 0 )
{
}
SomeClass::~SomeClass() {
}
void SomeClass::foo() {
}
void SomeClass::bar() {
}


А можно в .cpp файле добавить новые функции члены класса?
Код

void SomeClass::NewMetod() {

У меня компилятор визжит на такое, это вообще возможно?

Добавлено через 1 минуту и 40 секунд
private я имею в виду конечно.

Автор: borisbn 20.1.2011, 09:07
Цитата(KuMa1104 @  20.1.2011,  00:57 Найти цитируемый пост)
А можно в .cpp файле добавить новые функции члены класса?

Вот тебе и ответ.
Цитата(KuMa1104 @  20.1.2011,  00:57 Найти цитируемый пост)
У меня компилятор визжит на такое, это вообще возможно?

Нет. К сожалению.

Автор: KuMa1104 20.1.2011, 23:20
Цитата(borisbn @  20.1.2011,  09:07 Найти цитируемый пост)
Вот тебе и ответ.
Цитата(KuMa1104 @  20.1.2011,  00:57 )
У меня компилятор визжит на такое, это вообще возможно?

Да пожалуй действительно железный довод)

Автор: bsa 20.1.2011, 23:34
KuMa1104, а почему нельзя и в объявление класса добавить?

Автор: mes 20.1.2011, 23:51
Цитата(borisbn @  19.1.2011,  10:54 Найти цитируемый пост)
  в h-файлах класс описывается, а в cpp-файлах - определяется. 

 smile,
Цитата

A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the
class-specifier.

т.е. определение (definition) класса "происходит" в хидере.. 
 smile 

Автор: borisbn 21.1.2011, 00:16
Цитата(mes @  20.1.2011,  23:51 Найти цитируемый пост)
определение (definition)

перевод definition:

определение
четкость
описание
дефиниция
толкование
резкость
точность
ясность

Т.о. вопрос только в переводе, а если прочитать полностью
Цитата(borisbn @  19.1.2011,  11:54 Найти цитируемый пост)
Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора

а не выдёргивать, то получается вполне стройно smile

Автор: mes 21.1.2011, 00:21
Цитата(borisbn @  20.1.2011,  23:16 Найти цитируемый пост)
Т.о. вопрос только в переводе, а если прочитать полностью

нет, вопрос в устоявшихся терминах smile

Добавлено @ 00:24
Цитата(borisbn @  20.1.2011,  23:16 Найти цитируемый пост)
, а если прочитать полностью

Цитата(KuMa1104 @  19.1.2011,  23:57 Найти цитируемый пост)
 Описание класса - есть интерфейс 

Цитата(KuMa1104 @  19.1.2011,  23:57 Найти цитируемый пост)
. Определение класса - это уже не договор, а испольнение договора, 

 smile  smile 

Автор: borisbn 21.1.2011, 07:19
mes, ОК, сдаюсь. Не силён в терминологии smile
Скажи, пожалуйста, как в устоявшемся виде называют интерфейс класса, а как - реализацию его функций ?

Автор: mes 21.1.2011, 11:57
class Class; // объявление класса

class Class { 
       void f();  // объявление (прототипа) функции-члена
}; // определение класса

void Class::f() {} // определение функции-члена


Автор: borisbn 21.1.2011, 15:15
mes, я прекрасно понимаю, что о терминологии (тем более о переводе) можно спорить долго и, практически всегда, безрезультатно, однако...

Цитата(mes @  21.1.2011,  11:57 Найти цитируемый пост)
class Class; // объявление класса

чесслово, всегда считал это предварительным объявлением (или предобъявлением) ...

а по поводу 
Цитата(mes @  21.1.2011,  11:57 Найти цитируемый пост)
}; // определение класса

http://citforum.ru/programming/cpp_march/cpp_065.shtml
нашёл гениальную фразу
Цитата

Как сказано в Справочном руководстве по C++, "Если бы не исторические причины, объявление класса следовало называть определением класса".


так что предлагаю ничью smile

Автор: mes 21.1.2011, 18:31
Цитата(borisbn @  21.1.2011,  14:15 Найти цитируемый пост)
я прекрасно понимаю, что о терминологии (тем более о переводе) можно спорить долго и, практически всегда, безрезультатно, однако...

в данном случае спор не о словax "определение" и "описание"..  а о том, что определение/описание класса не затрагивает определение функций-членов..


Цитата(borisbn @  21.1.2011,  14:15 Найти цитируемый пост)
всегда считал это предварительным объявлением (или предобъявлением) ...

будет ли это объявление предварительным, зависит от того, известно ли уже это имя или нет.. 
Код

class Class; // forward declaration
class Class {}; //  declaration by definition
class Class; // backward declaration


Цитата(borisbn @  21.1.2011,  14:15 Найти цитируемый пост)
вот тут
нашёл гениальную фразу

сейчас почитаю.. 

Автор: baldina 21.1.2011, 18:31
KaraKum, используешь "нарекание" с странном, не общеупотребительном значении. звучит забавно
http://ru.wiktionary.org/wiki/%D0%BD%D0%B0%D1%80%D0%B5%D0%BA%D0%B0%D0%BD%D0%B8%D0%B5

Цитата(KaraKum @  18.1.2011,  16:32 Найти цитируемый пост)
все эти проблемы решаются как сами собой разумеющиеся после должного проектирования программы

о проектировании структуры кода, его организации и спрашивает ТС

Цитата(efpies @  19.1.2011,  21:30 Найти цитируемый пост)
 Или компилятор будет знать "по умолчанию" о существовании cpp-файла

efpies, в С/С++ используется т.н. раздельная компиляция, т.е. компилятор знает лишь о том файле, который компилирует в данный момент. содержимое включаемого файла в буквальном смысле подставляется в место директивы #include и компилируется результат.
таким образом заголовочные файлы являются средством связи между файлами .сpp, при помощи них объявляются типы и переменные, определенные в другом файле.
отдельный файл в C/C++ является не только единицей компиляции, но и средством структуризации программ (другие средства - функции, структуры и классы, пространства имен). К ним в общем случае применимы те же правила, что и к любым средствам структуризации: одна задача (тема, понятие) - один файл (класс, функция). интуитивно понять, как это лучше сделать, можно посмотрев на содержимое стандартных заголовков: cmath, ctime, vector, map, iostream, string.
Если речь идет о классах, то один заголовок - один класс (плюс, возможно, классы, связанные с ним и только с ним непосредственно. например string и string_iterator).
Конечно, в любом правиле бывают исключения, все должно быть по уму и без фанатизма.
Для упрощения анализа и отладки, для сокращения времени компиляции число связей в проекте, в т.ч. связей между файлами, стараются уменьшить.
пример borisbn вполне иллюстрирует основу такого подхода.

Добавлено через 12 минут и 30 секунд
mes, borisbn, не спорьте. в русскоязычной терминологии на эту тему небольшой бардак.
объявление (declaration) - ввод идентификатора в текущую область видимости. при этом объявление может быть определением. а может и не быть, как, например, опережающее объявление.

Автор: mes 21.1.2011, 18:44
Цитата(mes @  21.1.2011,  17:31 Найти цитируемый пост)
сейчас почитаю.. 

о нет, такое читать не буду..  smile

Цитата(borisbn @  21.1.2011,  14:15 Найти цитируемый пост)
так что предлагаю ничью  

ну ну, пожалуйста.. не буду Вас разубеждать.. продолжайте читать Марченко.. smile

Добавлено через 3 минуты и 12 секунд
Цитата(baldina @  21.1.2011,  17:31 Найти цитируемый пост)
 не спорьте. в русскоязычной терминологии на эту тему небольшой бардак.


Цитата(mes @  21.1.2011,  17:31 Найти цитируемый пост)
в данном случае спор не о словax "определение" и "описание"..  а о том, что определение/описание класса не затрагивает определение функций-членов..

 smile 

Цитата(baldina @  21.1.2011,  17:31 Найти цитируемый пост)
 при этом объявление

как раз конфликта между "объявление" и "определение" нету.. 
есть спор какое из слов "определение" или "описание" подходит в качестве перевода для "definition" в некоторых случаях... 

Автор: baldina 21.1.2011, 18:50
Цитата(mes @  21.1.2011,  18:44 Найти цитируемый пост)
Цитата(mes @  21.1.2011,  17:31 )
в данном случае спор не о словax "определение" и "описание"..  а о том, что определение/описание класса не затрагивает определение функций-членов..

с этим borisbn вроде бы и не спорил. а насчет перевода... definition можно перевести как описание. если рядом нет declaration.

Автор: mes 21.1.2011, 19:06
Цитата(baldina @  21.1.2011,  17:50 Найти цитируемый пост)
с этим borisbn вроде бы и не спорил. 


Цитата(borisbn @  20.1.2011,  23:16 Найти цитируемый пост)

Т.о. вопрос только в переводе, а если прочитать полностью
Цитата(borisbn @  19.1.2011,  11:54 )
Описание класса - есть интерфейс (договор, контракт) между тем, кто его создаёт и тем, кто его будет использовать. Определение класса - это уже не договор, а испольнение договора

а не выдёргивать, то получается вполне стройно 

 smile

Добавлено @ 19:08
Цитата(baldina @  21.1.2011,  17:50 Найти цитируемый пост)
definition можно перевести как описание. 

да дело не в том как перевести это definition, a в том, к чему его применили smile

Автор: baldina 21.1.2011, 19:09
ну ладно, ладно  smile 
определение с реализацией попутали. С++ запутанный язык  smile 

Автор: efpies 22.1.2011, 02:40
Всем спасибо за подсказки. smile Многое прояснилось, всё работает, как надо.

Цитата(borisbn @  19.1.2011,  11:54 Найти цитируемый пост)
Код

#if !defined( _SOME_CLASS_USING_H_INCLUDED_ )
#define _SOME_CLASS_USING_H_INCLUDED_

class SomeClass;   // Вот так

class SomeClassUsing
{
   public:
       SomeClassUsing(); 
       ~SomeClassUsing();

   private:
       SomeClass * m_someClass;
};
#endif //!defined( _SOME_CLASS_USING_H_INCLUDED_ )

Правда  просто объявить не получится, если SomeClassUsing должен наследовать SomeClass. Нужно подключать SomeClass.h

Автор: mes 22.1.2011, 12:15
Цитата(efpies @  22.1.2011,  01:40 Найти цитируемый пост)
Правда  просто объявить не получится, если SomeClassUsing должен наследовать SomeClass.

для наследования нужно иметь полное определение наследуемого предка.. т.е. объявления недостаточно
также полное определение нужно для создания/удаления, обращения к составляющим(членам), sizeof, и т.д..
объявления достаточно для использования  ссылки или указателя.. 


Автор: efpies 23.1.2011, 10:02
Возникла такая проблема: некоторые методы считаются неописанными (unresolved external), их нужно описать именно в заголовочном файле. С чем это может быть связано?

Автор: efpies 23.1.2011, 10:18
UPD: с inline-функциями такая штука

Автор: bsa 23.1.2011, 10:20
efpies, почитай определение встраиваемых функций. Если лень, то в двух словах - тело inline функции должно быть в хидере.

Автор: baldina 24.1.2011, 12:23
Цитата(bsa @  23.1.2011,  10:20 Найти цитируемый пост)
в двух словах - тело inline функции должно быть в хидере. 

efpies, тут главное не то, что тело inline функции в хидере, а что оно должно быть доступно в момент компиляции. 
в .h его помещают именно для этой цели.

Автор: semibug 24.1.2011, 15:00
Хочу обратить внимание на фундамент - заголовочные файлы всего лишь программистское соглашение, компилятор (канонический) ничего про них не знает.
Собственно компилирование начинается уже после обработки текста препроцессором, который поставит на место #include текст из соответствующего файла. Не важно какое у него будет расширение и имя, хоть cpp, хоть exe.

Как то раз попалось даже такое извращение - вместо makefile с перечислением сырцов, компилировался один файл, содержащий #include всех остальных файлов проекта.

Присоединяюсь к мнению гуру, один класс - один файл, и, imho, чем он меньше, тем лучше.




Автор: wildwolf 24.1.2011, 22:34
я извиняюсь, ребят, помогите пожалуста..
сам изучал с++ .. а тут девушка с задачками подошла, не могу разобраться..
подскажите..
"Дано тело функции main(). Определить что будет выведено на экран в результате выполнения данного кода, и почему (дать пояснения к ответу).
Код:
int n=5;
char * b="0";
printf("%u\n", open("f", O_RONLY));
close(fd);
Примечание: Файла f не существует."
и вторая-
"Пояснить результаты работы программы
#include<unistd.h>
main(){
printf("один/n");
fork();
fork();
printf("два/n");
wait();
printf("три/n");
printf("четыре/n");
}"
или хотя б подскажите где и скать и что за язык..спасибо заранее..

Автор: baldina 25.1.2011, 10:28
C++ изучал, говоришь?  smile

Добавлено через 11 минут и 42 секунды
язык С. с небольшими (непринципиальными) исправлениями будет компилироваться как С++.

первая программа выведет Очень Большое Число, соотв. максимальному беззнаковому целому на целевой системе. это потомучто open() возвращает int(-1), а спецификация формата вывода - беззнаковая. в 32-битной среде это 4294967295.

вторая программа предназначена для исполнения в POSIX-совместимой среде. *nix например. вызов fork() порождает новый процесс (клон текущего) в точке вызова. wait () приостанавливает текущий процесс, пока один из порожденных процессов не завершится (или не ждет, если порожденных процессов нет). так что теперь можешь сам сообразить что она выведет. 

Автор: borisbn 25.1.2011, 10:55
baldina, "+1" smile

надо бы http://forum.vingrad.ru/forum/topic-242693/view-all.html скопировать

#inclyde опять же улыбнул

Автор: wildwolf 25.1.2011, 11:13
спасиб огромное smile 
изучал, но только поверхносно..
"include" - опечатался=)

Автор: Ignat 25.1.2011, 11:23
Цитата(baldina @  25.1.2011,  10:28 Найти цитируемый пост)
так что теперь можешь сам сообразить что она выведет.  


Это, кстати, одна из моих любимых задачек. Выведет она не то, что ожидается =)
Чтобы она вывела, что ожидается, нужно ставить flush() после каждого вывода.


Автор: wildwolf 25.1.2011, 11:29
а что она выведет? если не секрет)

Автор: baldina 25.1.2011, 11:38
Цитата(Ignat @  25.1.2011,  11:23 Найти цитируемый пост)
не то, что ожидается

 smile 
что-то мне подсказывает, что от девушки требуют "что ожидается"
Цитата

Пояснить результаты работы программы

интересно, результат приводится?

Автор: Ignat 25.1.2011, 11:41
В зависимости от компилятора и платформы:
Цитата

один
два
три
четыре
один
два
три
четыре
один
два
три
четыре
один
два
три
четыре

либо, если сброс буфера будет происходить после каждого вывода
Цитата

один
два
два
два
два
три
четыре
три
четыре
три
четыре
три
четыре

На практике, со вторым поведением сталкивался, кажется, в цигвине.

Автор: wildwolf 25.1.2011, 11:44
спасибо!=)

Автор: Ignat 25.1.2011, 11:47
Цитата(wildwolf @  25.1.2011,  11:44 Найти цитируемый пост)
спасибо!=)

За что?
ни тот, ни другой ответ не гарантирован =)

Автор: wildwolf 25.1.2011, 11:50
спасибо, что хоть чем-то помогли..
а там случайно не 
"один
 один
 один
 два
 три 
 четыре" ?

Автор: Ignat 25.1.2011, 11:57
Цитата(wildwolf @  25.1.2011,  11:50 Найти цитируемый пост)
а там случайно не 

Ну это должна быть очень большая случайность, разве что сидеть на изготовку с kill -2, да и то снайпер должен быть знатный.

Автор: baldina 25.1.2011, 12:22
wildwolf, Ignat, "один" выведется только один раз. в корневом процессе.

Автор: Ignat 25.1.2011, 12:29
Цитата(baldina @  25.1.2011,  12:22 Найти цитируемый пост)
"один" выведется только один раз. в корневом процессе. 


baldina, на чем проверял?
В своё время проверял на нескольких системах. Результат - процесс форкается вместе с буфферами, следовательно, "один" выведется 4 раза.

Автор: baldina 25.1.2011, 12:32
Цитата

если сброс буфера будет происходить после каждого вывода

не успеет. сейчас очень быстрые процессоры ;-)

Добавлено через 14 минут и 46 секунд
Цитата(Ignat @  25.1.2011,  12:29 Найти цитируемый пост)
baldina, на чем проверял?

не проверял. 

Автор: baldina 25.1.2011, 12:48
проверил

Код

Linux 2.6.18-194.26.1.el5 #1 SMP Tue Nov 9 12:54:40 EST 2010 i686 i686 i386 GNU/Linux


Код

один
два
три
четыре
два
три
четыре
два
два
три
четыре
три
четыре

Автор: Ignat 25.1.2011, 12:55
Тоже проверил
Linux 2.6.32-27-generic
gcc 4.4.3

Цитата

1
2
2
2
3
4
2
3
4
3
4
3
4


Таки каждый \n приводит к flush. Убираем LF и получаем 1234123412341234.

Добавлено через 57 секунд
Сыплю на голову мусор (пепла нет), про опустошение буффера десятым символом забыл напрочь.

Автор: wildwolf 27.1.2011, 21:43
спасиб ребят, оч помогли!=) прокатило! smile   smile  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)