Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
интересующийся
311 / 282 / 93
Регистрация: 25.09.2010
Сообщений: 1,056

Пораздельная компиляция и повоторное переопределением в gcc

06.05.2013, 22:55. Показов 980. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Пытаюсь разобрать пример с учебника. Теоритически вроде всё делаю правильно...
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ilyuha21st@coldshoot:~/Projects/calc$ g++ calc.cpp -c -o calc.o
ilyuha21st@coldshoot:~/Projects/calc$ g++ main.cpp -c -o main.o
ilyuha21st@coldshoot:~/Projects/calc$ g++ main.o calc.o -o prog
calc.o:(.bss+0x0): multiple definition of `Driver::no_of_errors'
main.o:(.bss+0x0): first defined here
calc.o:(.bss+0x8): multiple definition of `Lexer::string_value'
main.o:(.bss+0x8): first defined here
calc.o:(.bss+0x10): multiple definition of `Lexer::number_value'
main.o:(.bss+0x10): first defined here
calc.o:(.data+0x0): multiple definition of `Lexer::curr_token'
main.o:(.data+0x0): first defined here
calc.o:(.bss+0x20): multiple definition of `Driver::table'
main.o:(.bss+0x20): first defined here
calc.o:(.bss+0x50): multiple definition of `Driver::input'
main.o:(.bss+0x50): first defined here
collect2: error: ld returned 1 exit status
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// calc.h
#ifndef _CALCULATOR_HEADER_
#define _CALCULATOR_HEADER_
 
#include <string>
#include <iostream>
#include <map>
 
namespace Driver
{
    int no_of_errors = 0;
}
 
namespace Error
{
    struct Zero_divide
    {
        Zero_divide() { Driver::no_of_errors++; }
    };
 
    struct Syntax_error
    {
        Syntax_error(const char* p) { err = p; Driver::no_of_errors++; }
 
        const char* err;
        const char* what()
        {
            return err;
        }
    };
}
 
namespace Lexer
{
    enum Token_value 
    {
        NAME,       NUMBER,     END,       
        PLUS='+',   MINUS='-',  MUL='*',    DIV='/',
        PRINT=';',  ASSIGN='=', LP='(',     RP=')'      
    };
 
    std::string string_value;
    double number_value;
    Token_value curr_token = PRINT;
 
    Token_value get_token();
}
 
namespace Parser
{
    double expr(bool);
    double term(bool);
    double prim(bool);
}
 
namespace Driver
{
    std::map<std::string, double> table;
    std::istream* input;
    void skip();
 
    using Parser::expr;
}
 
#endif
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//calc.cpp
#include "calc.h"
#include <cctype>
 
Lexer::Token_value Lexer::get_token()
{
    char ch;
    
    do
    {
        if (!Driver::input->get(ch))
        {
            return curr_token = END;
        }
    } while (ch != '\n' && isspace(ch));
 
    switch (ch)
    {
        case 0:
            return curr_token = END;
        case ';':
        case '\n':
            return curr_token = PRINT;
        case '+':
        case '-':
        case '/':
        case '*':
        case '=':
        case '(':
        case ')':
            return curr_token = Token_value(ch);
        case '0':   case '1':   case '2':   case '3':   case '4':
        case '5':   case '6':   case '7':   case '8':   case '9':
        case '.':
            Driver::input->putback(ch);
            *Driver::input >> number_value;
            return curr_token = NUMBER;
        default:
            if (isalpha(ch))
            {
                string_value = ch;
                while (Driver::input->get(ch) && isalnum(ch))
                {
                    string_value.push_back(ch);
                }
                return curr_token = NAME;
            }
            throw Error::Syntax_error("bad token");
    }
}
 
double Parser::expr(bool get)
{
    double left = term(get);
 
    for ( ; ; )
    {
        switch (Lexer::curr_token)
        {
            case Lexer::PLUS:
                left += term(true);
                break;
            case Lexer::MINUS:
                left -= term(true);
                break;
            default:
                return left;
        }
    }
}
 
double Parser::term(bool get)
{
    double left = prim(get);
    
    for ( ; ; )
    {
        switch (Lexer::curr_token)
        {
            case Lexer::MUL:
                left *= prim(true);
                break;
            case Lexer::DIV:
                if (double v = prim(true))
                {
                    left /= v;
                }
                throw Error::Zero_divide();
            default:
                break;
        }
    }
}
 
double Parser::prim(bool get)
{
    if (get)
    {
        Lexer::get_token();
    }
 
    switch (Lexer::curr_token)
    {
        case Lexer::NUMBER:
            {
                double v = Lexer::number_value;
                Lexer::get_token();
                return v;
            }
        case Lexer::NAME:
            {
                double& v = Driver::table[Lexer::string_value];
                if (Lexer::get_token() == Lexer::ASSIGN)
                {
                    v = expr(true);
                }
                return v;
            }
        case Lexer::MINUS:
            return prim(true);
        case Lexer::LP:
            {
                double e = expr(true);
                if (Lexer::curr_token != Lexer::ASSIGN)
                {
                    throw Error::Syntax_error("')' expected");
                }
                Lexer::get_token();
                return e;
            }
        default:
            throw Error::Syntax_error("pimary expected");
    }
}
 
 
void Driver::skip()
{
    char ch;
 
    while (*input)
    {
        input->get(ch);
 
        switch (ch)
        {
            case '\n':
            case ';':
                break;
        }
    }
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 // main.cpp
#include "calc.h"
#include <iostream>
#include <sstream>
 
int main(int argc, const char* argv[])
{
    switch (argc)
    {
        case 1:
            Driver::input = &std::cin;
            break;
        case 2:
            Driver::input = new std::stringstream(argv[1]);
            break;
        default:
            std::cerr << "to many arguments" << std::endl;
            return 1;
    }
 
    while (*Driver::input)
    {
        try
        {
            Lexer::get_token();
            if (Lexer::curr_token == Lexer::END)
            {
                break;
            }
            if (Lexer::curr_token == Lexer::PRINT)
            {
                continue;
            }
            std::cout << Driver::expr(false) << std::endl;
        }
        catch (Error::Zero_divide)
        {
            std::cerr << "divide by zero" << std::endl;
            Driver::skip();
        }
        catch (Error::Syntax_error e)
        {
            std::cerr << "error: " << e.what() << std::endl;
            Driver::skip();
        }
    }
 
    if (Driver::input != &std::cin)
    {
        delete Driver::input;
    }
 
    return Driver::no_of_errors;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.05.2013, 22:55
Ответы с готовыми решениями:

gcc компиляция
Проблема возникла при компиляции проекта code::block. При build and run все работает, в папке bin проекта появляется .exe Но...

Компиляция (gcc)
Добрый вечер! После компиляции текстовый файл становится вдруг двоичным, как следствие его невозможно открыть для исправлений. Почему? ...

Компиляция gcc
Подскажите как в VS скомпилировать программу с помощью компилятора gcc

4
Higher
 Аватар для diagon
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
06.05.2013, 23:18
У вас один и тот же хедер включается в 2 cpp'шника. Линкер не знает, что делать в такой ситуации.
Вы можете помочь ему, если объявите ваши функции как inline либо static.

Ну либо переписать все в ООП-шном стиле через классы.
1
интересующийся
311 / 282 / 93
Регистрация: 25.09.2010
Сообщений: 1,056
07.05.2013, 00:11  [ТС]
Пробую я различные комбинации, но что-то всё равно не получается... Интересно, а как тогда пишутся программы на С? Всё время static использовать?
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
07.05.2013, 00:14
Цитата Сообщение от xtorne21st Посмотреть сообщение
Теоритически вроде всё делаю правильно...
Теоретически в хедерах только объявляют. Поиск соответствующих объявлениям определений задача линкера.

Добавлено через 1 минуту
Цитата Сообщение от xtorne21st Посмотреть сообщение
Всё время static использовать?
можно для объявления переменных указать extern, прототипы функций по умолчанию extern
1
интересующийся
311 / 282 / 93
Регистрация: 25.09.2010
Сообщений: 1,056
07.05.2013, 19:20  [ТС]
Croessmah, спасибо что напомнили. Также вспомнил, что если использован модификатор const, то extern нужно задавать явно.

Добавлено через 6 минут
Хотя вот только что проверил на gcc и без extern всё ок компилируется.

Добавлено через 36 секунд
Ps. Врут в учебниках

Добавлено через 38 минут
Хотя, это скорей всего зависит от компилятора
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.05.2013, 19:20
Помогаю со студенческими работами здесь

Компиляция Objective-C в GCC
Пытаюсь выполнить компияцию кода Objective-C с помощью GCC на Windows. Для этого: 1. Установил Dev C++. В его состав входит MinGW,...

компиляция avr-gcc
Народ подскажите как компилировать проекты написанные с помощью LUFA. 1 из командной строки. 2 из Atmel Studyo7 а в atmel studyo...

компиляция gcc и MSVC
Привет всем. Объясните, почему один и тот же код #include &quot;stdafx.h&quot; #include &lt;vector&gt; #include &lt;iostream&gt; #include...

Компиляция проекта в gcc
Здравствуйте, форумчане! Прошу помочь разобраться! Есть программа, представленная в 3х файлах. В первом содержится описание класса...

Компиляция бинарника на gcc
Задача: нужно скомпилировать сырой бинарник на gcc. Он будет грузиться по адресу 0x10000 и туда же будет передаваться управление. И мне...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru