Форум программистов, компьютерный форум, киберфорум
C (Си)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 30.11.2015
Сообщений: 15

Перегрузка функции через макрос с зависимостью от количества и типа переданных параметров еще и с вариаблик

02.07.2020, 01:35. Показов 1387. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.

На чистоту, я не осилил макросы.

Провел весь день, чтобы попытаться вызвать функцию с помощью макроса в зависимости от количества и типа переданных параметров.
Прошу помощи.

Код с тестовой функцией на которой можно проводить эксперименты:
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
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
 
/*
ПРОМЕЖУТОЧНАЯ МАКРОПОДСТАНОВКА
log();                           //-> log_____ (__LINE__, __COUNTER__, NUL, NUL, NUL, NUL)
log(L_1);                        //-> log_A___ (__LINE__, __COUNTER__, L_1, NUL, NUL, NUL)
log(L_1, L_2);                   //-> log_AB__ (__LINE__, __COUNTER__, L_1, L_2, NUL, NUL)
log(L_1, "hello");               //-> log_A_C_ (__LINE__, __COUNTER__, L_1, NUL, MES, NUL)
log(L_1, "hello %s", 1);         //-> log_A_CD (__LINE__, __COUNTER__, L_1, NUL, MES, __VA_ARGS__)
log(L_1, L_2, "hello");          //-> log_ABC_ (__LINE__, __COUNTER__, L_1, L_2, MES, NUL)
log(L_1, L_2, "hello %s", 1);    //-> log_ABCD (__LINE__, __COUNTER__, L_1, L_2, MES, __VA_ARGS__)
 
---> void log_func(uintmax_t line, uintmax_t coun, uintmax_t L_1, uintmax_t L_2, char *mesg, ...)
*/
 
#define NUL 0 // NULL
 
//ОТЛАДКА - ДВА ТИПА СООБЩЕНИЙ, включать по одному иначе будет белиберда
//выводит две строки
//t - пример для сравнения,
//f - результат работы функции
#define print_t1(m, ...) //printf(m, ##__VA_ARGS__)
//выводит построчно каждый параметр
#define print_t2(m, ...) printf(m, ##__VA_ARGS__)
 
void log_func(uintmax_t line, uintmax_t coun, uintmax_t L_1, uintmax_t L_2, char *mesg, ...) {
    print_t1("%ld : %ld\nf log_", coun, line);
    print_t2("%ld : %ld\n", coun, line);
 
    if (L_1 == NUL) {
        print_t1("_");
        print_t2("A: L_1 == NUL\n");
    } else {
        print_t1("A");
        print_t2("A: L_2 == %ld\n", L_1);
    }
    if (L_2 == NUL) {
        print_t1("_");
        print_t2("B: L_2 == NUL\n");
    } else {
        print_t1("B");
        print_t2("B: L_2 == %ld\n", L_2);
    }
    if (mesg == NUL) {
        print_t1("_");
        print_t2("C: MES == NUL\n");
    } else {
        print_t1("C");
        print_t2("C: MES == %s\n", mesg);
    }
 
    if (mesg != NUL) {
        va_list list;
        va_list list_copy;
 
        va_copy(list_copy, list);
 
        va_start(list_copy, mesg);
        uintmax_t flag = va_arg(list_copy, uintmax_t);
        va_end(list_copy);
 
        if (flag == NUL) {
            print_t1("_");
            print_t2("D: ARG == NUL\n");
        } else {
            print_t1("D ==> ");
            print_t2("D: ARG ==> ");
 
            va_start(list, mesg);
            vprintf(mesg, list);
            va_end(list);
        }
    } else {
        va_list list;
        va_start(list, mesg);
        uintmax_t flag = va_arg(list, uintmax_t);
        va_end(list);
 
        if (flag == NUL) {
            print_t1("_");
            print_t2("D: ARG == NUL\n");
        } else {
            print_t1("E");
            print_t2("D: ERROR!!\n");
        }
    }
    print_t1("\n");
    print_t2("\n\n");
}
 
int main() {
    uintmax_t L_1 = 1;
    uintmax_t L_2 = 2;
 
    /*ТЕСТ ФУНКЦИИ*/
    log_func(__LINE__, __COUNTER__, NUL, NUL, NUL, NUL); //0
    print_t1("t log_____ \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, NUL, NUL, NUL); //1
    print_t1("t log_A___ \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, L_2, NUL, NUL); //2
    print_t1("t log_AB__ \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, NUL, "H", NUL); //3
    print_t1("t log_A_C_ \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, NUL, "%d", 3); //4
    print_t1("t log_A_CD \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, NUL, "%s", "h"); //5
    print_t1("t log_A_CD \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, NUL, "h%s", "w"); //6
    print_t1("t log_A_CD \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, NUL, "%s%s", "h", "w"); //7
    print_t1("t log_A_CD \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, L_2, "H", NUL); //8
    print_t1("t log_ABC_ \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, L_2, "H%s", "W"); //9
    print_t1("t log_ABCD \n\n");
 
    log_func(__LINE__, __COUNTER__, L_1, L_2, "H%d", 4); //10
    print_t1("t log_ABCD \n\n");
 
    //функция с намеренной ошибкой (влияет только на внутреннее поведение)
    log_func(__LINE__, __COUNTER__, NUL, NUL, NUL, 1); //11
    print_t1("t log____E \n\n"); 
 
    /*
    ПРИМЕР ИСПОЛЬЗОВАНИЯ МАКРОСА КОТОРЫЙ ДОЛЖЕН ВЫЗЫВАЕТ ФУНКЦИЮ log_func
    log();
    log(L_1);
    log(L_1, L_2);
    log(L_1, "hello"); 
    log(L_1, "hello %s", 1);
    log(L_1, L_2, "hello");
    log(L_1, L_2, "hello %s", 1);
    */
 
    return 0;
}
Вся сложность заключается в том что, не достаточно посчитать количество параметров, а нужно еще и опираться на их тип.

Начинал с этого треда, Дизайн и эволюция: перегрузка макросов дальше пошёл бродить по форуму и интернету. Но увы.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.07.2020, 01:35
Ответы с готовыми решениями:

Считывание параметров, переданных через командную строку
Всем привет! Есть у кого-нибудь пример считывания нескольких параметров, переданных через командную строку? Поделитесь пожалуйста ;)...

Поведение функции в зависимости от количества переданных аргументов
Класс Point должен содержать новый метод, возвращающий расстояние от точки, которую он описывает, до другой точки.Другая точка является...

Функция с переменным числом параметров, как узнать кличество переданных параметров?
Добрый вечер, можно не использовать int n, а каким то другим способом узнать количество переданных аргументов в функцию и адрес? int suma...

16
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
02.07.2020, 21:15
Цитата Сообщение от RR-Zz Посмотреть сообщение
макрос с зависимостью от количества и типа переданных параметров
А почему бы не написать обычные функции с переменным количеством параметров как, например, printf?
0
0 / 0 / 0
Регистрация: 30.11.2015
Сообщений: 15
03.07.2020, 15:02  [ТС]
Получилось вот так.

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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
 
//ОТЛАДКА - ТРИ ТИПА СООБЩЕНИЙ
// 0 - вывод через макрос
// 1 - отладка коротким способом
// 2 - отладка длинным способом
#define DEBEG_LEVEL 0
 
#if DEBEG_LEVEL == 0
#define DEBEG_LEVEL_0
#define print_t0(m, ...) printf(m, ##__VA_ARGS__)
#else
#define print_t0(m, ...)
#endif
 
#if DEBEG_LEVEL == 1
//выводит две строки
//t - пример для сравнения,
//f- результат работы функции
#define print_t1(m, ...) printf(m, ##__VA_ARGS__)
#else
#define print_t1(m, ...)
#endif
 
#if DEBEG_LEVEL == 2
//выводит посрочно каждый параметр
#define print_t2(m, ...) printf(m, ##__VA_ARGS__)
#else
#define print_t2(m, ...)
#endif
 
#define LOGGER_NULL 0 // NULL
 
static void logger_test(uintmax_t line, uintmax_t coun, uintmax_t L_1, uintmax_t L_2, char *mesg, ...) {
    print_t0("%03ld : %03ld - log_", coun, line);
    print_t1("%03ld : %03ld\nf log_", coun, line);
    print_t2("%03ld : %03ld\n", coun, line);
 
    if (L_1 == LOGGER_NULL) {
        print_t0("_");
        print_t1("_");
        print_t2("A: L_1 == NUL\n");
    } else {
        print_t0("A");
        print_t1("A");
        print_t2("A: L_2 == %ld\n", L_1);
    }
    if (L_2 == LOGGER_NULL) {
        print_t0("_");
        print_t1("_");
        print_t2("B: L_2 == NUL\n");
    } else {
        print_t0("B");
        print_t1("B");
        print_t2("B: L_2 == %ld\n", L_2);
    }
    if (mesg == LOGGER_NULL) {
        print_t0("_");
        print_t1("_");
        print_t2("C: MES == NUL\n");
    } else {
        print_t0("C");
        print_t1("C");
        print_t2("C: MES == %s\n", mesg);
    }
 
    if (mesg != LOGGER_NULL) {
        va_list list;
        va_list list_copy;
 
        va_copy(list_copy, list);
 
        va_start(list_copy, mesg);
        uintmax_t flag = va_arg(list_copy, uintmax_t);
        va_end(list_copy);
 
        if (flag == LOGGER_NULL) {
            print_t0("_");
            print_t1("_");
            print_t2("D: ARG == NUL\n");
        } else {
            print_t0("D ==> ");
            print_t1("D ==> ");
            print_t2("D: ARG ==> ");
 
            va_start(list, mesg);
            vprintf(mesg, list);
            va_end(list);
        }
    } else {
        va_list list;
        va_start(list, mesg);
        uintmax_t flag = va_arg(list, uintmax_t);
        va_end(list);
 
        if (flag == LOGGER_NULL) {
            print_t0("_");
            print_t1("_");
            print_t2("D: ARG == NUL\n");
        } else {
            print_t0("E");
            print_t1("E");
            print_t2("D: ERROR!!\n");
        }
    }
    print_t0("\n");
    print_t1("\n");
    print_t2("\n\n");
}
 
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
#define log_____() /*              */ logger_test(__LINE__, __COUNTER__, LOGGER_NULL, LOGGER_NULL, LOGGER_NULL, LOGGER_NULL) //0
#define log_A___(A) /*             */ logger_test(__LINE__, __COUNTER__, A, LOGGER_NULL, LOGGER_NULL, LOGGER_NULL)           //1
#define log_AB__(A, B) /*          */ logger_test(__LINE__, __COUNTER__, A, B, LOGGER_NULL, LOGGER_NULL)                     //2
#define log_A_C_(A, C) /*          */ logger_test(__LINE__, __COUNTER__, A, LOGGER_NULL, C, LOGGER_NULL)                     //2
#define log_ABC_(A, B, ...) /*     */ logger_test(__LINE__, __COUNTER__, A, B, __VA_ARGS__, LOGGER_NULL)                     //3
#define log_A_CD(A, C, ...) /*     */ logger_test(__LINE__, __COUNTER__, A, LOGGER_NULL, C, __VA_ARGS__)                     //3
#define log_ABCD(A, B, C, ...) /*  */ logger_test(__LINE__, __COUNTER__, A, B, C, __VA_ARGS__)                               //4
 
#define log_0() log_____()
#define log_1(A) log_A___(A)
 
//#define log_2(A, B) log_AB__(A, B)
#define log_2(A, BC) _Generic((A), int : log_2_BC(A, BC))
#define log_2_BC(A, BC) _Generic((BC), int : log_AB__(A, BC), char * : log_A_C_(A, BC))
 
//#define log_3(A, B, C) log_ABC_(A, B, C)
#define log_3(A, BC, ...) _Generic((A), int : log_3_BC_CD(A, BC, __VA_ARGS__))
#define log_3_BC_CD(A, BC, ...) _Generic((BC), int : log_3_B_C(A, BC, __VA_ARGS__), char * : log_3_C_D(A, BC, __VA_ARGS__))
#define log_3_B_C(A, BC, ...) log_ABC_(A, BC, __VA_ARGS__)
#define log_3_C_D(A, BC, ...) log_A_CD(A, BC, __VA_ARGS__)
 
//#define log_4(A, B, C, ...) log_ABCD(A, B, C, ##__VA_ARGS__)
#define log_4(A, B, C, ...) _Generic((A), int : log_4_B(A, B, C, __VA_ARGS__))
#define log_4_B(A, B, C, ...) _Generic((B), int : log_4_C(A, B, C, __VA_ARGS__), char * : log_4_D(A, B, C, __VA_ARGS__))
#define log_4_C(A, B, C, ...) log_ABCD(A, B, C, __VA_ARGS__)
#define log_4_D(A, B, C, ...) log_A_CD(A, B, C, __VA_ARGS__)
 
#define XXX_0() log_0()
#define XXX_A(A) log_1(A)
#define XXX_B(A, B) log_2(A, B)
#define XXX_C(A, B, C) log_3(A, B, C)
#define XXX_D(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_E(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_F(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_G(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_H(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_I(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_J(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_K(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_L(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_M(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_O(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_P(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_Q(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_R(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_S(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_T(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_U(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_V(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_W(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_X(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_Y(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
#define XXX_Z(A, B, C, ...) log_4(A, B, C, __VA_ARGS__)
 
#define XXX_x(x, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, FUNC, ...) FUNC
 
#define log(...) \
    XXX_x(, \
          ##__VA_ARGS__, \
          XXX_Z(__VA_ARGS__), \
          XXX_Y(__VA_ARGS__), \
          XXX_X(__VA_ARGS__), \
          XXX_W(__VA_ARGS__), \
          XXX_V(__VA_ARGS__), \
          XXX_U(__VA_ARGS__), \
          XXX_T(__VA_ARGS__), \
          XXX_S(__VA_ARGS__), \
          XXX_R(__VA_ARGS__), \
          XXX_Q(__VA_ARGS__), \
          XXX_P(__VA_ARGS__), \
          XXX_O(__VA_ARGS__), \
          XXX_N(__VA_ARGS__), \
          XXX_M(__VA_ARGS__), \
          XXX_L(__VA_ARGS__), \
          XXX_K(__VA_ARGS__), \
          XXX_J(__VA_ARGS__), \
          XXX_I(__VA_ARGS__), \
          XXX_H(__VA_ARGS__), \
          XXX_G(__VA_ARGS__), \
          XXX_F(__VA_ARGS__), \
          XXX_E(__VA_ARGS__), \
          XXX_D(__VA_ARGS__), \
          XXX_C(__VA_ARGS__), \
          XXX_B(__VA_ARGS__), \
          XXX_A(__VA_ARGS__), \
          XXX_0(__VA_ARGS__))
 
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
int main() {
#ifndef DEBEG_LEVEL_0
    uintmax_t L_1 = 1;
    uintmax_t L_2 = 2;
 
    logger_test(__LINE__, __COUNTER__, LOGGER_NULL, LOGGER_NULL, LOGGER_NULL, LOGGER_NULL); //0
    print_t1("t log_____ \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, LOGGER_NULL, LOGGER_NULL, LOGGER_NULL); //1
    print_t1("t log_A___ \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, L_2, LOGGER_NULL, LOGGER_NULL); //2
    print_t1("t log_AB__ \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, LOGGER_NULL, "H", LOGGER_NULL); //3
    print_t1("t log_A_C_ \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, LOGGER_NULL, "%d", 3); //4
    print_t1("t log_A_CD \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, LOGGER_NULL, "%s", "h"); //5
    print_t1("t log_A_CD \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, LOGGER_NULL, "h%s", "w"); //6
    print_t1("t log_A_CD \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, LOGGER_NULL, "%s%s", "h", "w"); //7
    print_t1("t log_A_CD \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, L_2, "H", LOGGER_NULL); //8
    print_t1("t log_ABC_ \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, L_2, "H%s", "W"); //9
    print_t1("t log_ABCD \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, L_2, "H%d", 4); //10
    print_t1("t log_ABCD \n\n");
 
    logger_test(__LINE__, __COUNTER__, L_1, L_2, "H %c %s %d", 'W', "!", 666); //10
    print_t1("t log_ABCD \n\n");
 
    //функция с намереной ошибкой
    logger_test(__LINE__, __COUNTER__, LOGGER_NULL, LOGGER_NULL, LOGGER_NULL, 1); //11
    print_t1("t log____E \n\n");
#endif
 
#define L_TEST 1
 
#ifdef DEBEG_LEVEL_0
    log(); //0
 
    log(L_TEST); //1
 
    log(L_TEST, L_TEST); //2
    log(L_TEST, "test"); //2
 
    log(L_TEST, L_TEST, "test"); //3
    log(L_TEST, "%s", "test");   //3
 
    log(L_TEST, "%c %s", 't', "test"); //3 + 1
 
    log(L_TEST, L_TEST, "H%s", "W");                  //4
    log(L_TEST, L_TEST, "H %c %s", 'W', "!");         //4 + 1
    log(L_TEST, L_TEST, "H %c %s %d", 'W', "!", 666); //4 + 2
 
    log(L_TEST, L_TEST, NULL, "W");    //4 + E
    log(L_TEST, L_TEST, NULL, "W", 1); //4 + 1 + E
 
    log(LOGGER_NULL, LOGGER_NULL, NULL, "W", 1); //4N + 1 + E
#endif
 
    return 0;
}
Если кто может, запустите у себя.
Интересуют ошибки которые будет выдавать компилятор.
через #define DEBEG_LEVEL 0 можно включить разный уровень отладки.

Если запустить ничего не меняя, должен получится вот такой вывод

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
000 : 254 - log_____
001 : 256 - log_A___
002 : 258 - log_AB__
005 : 259 - log_A_C_
006 : 261 - log_ABC_
009 : 262 - log_A_CD ==> test
011 : 264 - log_A_CD ==> t test
012 : 266 - log_ABCD ==> HW
014 : 267 - log_ABCD ==> H W !
016 : 268 - log_ABCD ==> H W ! 666
018 : 270 - log_AB_E
020 : 271 - log_AB_E
022 : 273 - log____E
0
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
03.07.2020, 21:45
Цитата Сообщение от RR-Zz Посмотреть сообщение
Если кто может, запустите у себя.
Ошибок нет, но куча варнингов.
Компилил на TDM-GCC 4.9.2
C++
1
Line 252: [Warning] passing argument 5 of 'logger_test' makes pointer from integer without a cast
0
0 / 0 / 0
Регистрация: 30.11.2015
Сообщений: 15
03.07.2020, 22:50  [ТС]
Цитата Сообщение от assemberist Посмотреть сообщение
Ошибок нет, но куча варнингов.
Об этом знаю, это происходит в _Generic, он почему-то перекрестно ругается, на преобразования, но функции подставляет правильно.

Этого можно избежать, если каждый вызов брать в #pragma

Code
1
2
3
4
5
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wint-conversion"
    log(1, 2); //2
    log(1, "test");
#pragma GCC diagnostic pop
Сейчас пытаюсь, сделать так, чтобы эта конструкция вызывалась вместе с log();
Но способа пока найти не могу..

Добавлено через 6 минут
Цитата Сообщение от assemberist Посмотреть сообщение
Компилил на TDM-GCC 4.9.2
Благодарю!

Сам компилировал GCC 7.5.0.

Вот бы еще на MSVC и MinGW проверить. Есть желающие?
0
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
04.07.2020, 00:43
Цитата Сообщение от RR-Zz Посмотреть сообщение
Вся сложность заключается в том что, не достаточно посчитать количество параметров, а нужно еще и опираться на их тип.
А как тогда printf по формат-строке все определяет? Если ты не знал, то указатели можно кастовать. И тут очень кстати void*.
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
#include <stdio.h>
#include <stdint.h>
 
void logger(const char* src, ...){
    char* ptr = src;
    void* arg = &src+1;
 
    do{
        if(*ptr != '%') {   // кидает простые символы на вывод
            putchar(*ptr);
            continue;
        }
        else{               // встретили спец. символ. Можно использовать любой другой
            ptr++;
            switch(*ptr){   // проверяем, что хотели передать
                case 's':   // строку
                    printf(*(char**)arg);
                    arg = (char**)arg + 1; // переходим к следующему аргументу
                    break;
                case 'i':   // число
                    printf("%i", *((int*)arg));
                    arg = (char**)arg + 1; // переходим к следующему аргументу
                    break;
                case 'v':   // или сделать что-нибудь не используя параметр
                    printf("that string is hardkoded");
                    break;
                default:
                    putchar('%');
            }
        }
    }while(*++ptr);         // При достижении конца строки выходим
}
 
int main(){
    logger("qwe %s %i %s %v qwe", "hello", 3, "rtyu");
}
0
0 / 0 / 0
Регистрация: 30.11.2015
Сообщений: 15
04.07.2020, 01:01  [ТС]
Цитата Сообщение от assemberist Посмотреть сообщение
printf по формат-строке все определяет?
Именно!

Но у меня было две цели
1) Это сделать обязательным параметром L_1 и (полу)обязательным параметр L_2
2) Уйти от форматированной строки. Зачем? Ну вот захотелось.. сделать человеческий интерфейс, а не городить форматированную строку для 3-х параметров, а потом еще одну такую же для вывода print.

Поставленную задачу считаю решенной. А если есть другие предложения, то сначала проверьте их на прохождения этих тестов.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   
    log(); //0
 
    log(L_TEST); //1
 
    log(L_TEST, L_TEST); //2
    log(L_TEST, "test"); //2
 
    log(L_TEST, L_TEST, "test"); //3
    log(L_TEST, "%s", "test");   //3
 
    log(L_TEST, "%c %s", 't', "test"); //3 + 1
 
    log(L_TEST, L_TEST, "H%s", "W");                  //4
    log(L_TEST, L_TEST, "H %c %s", 'W', "!");         //4 + 1
    log(L_TEST, L_TEST, "H %c %s %d", 'W', "!", 666); //4 + 2
0
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
04.07.2020, 01:15
Цитата Сообщение от RR-Zz Посмотреть сообщение
человеческий интерфейс, а не городить форматированную строку для 3-х параметров
Это тема отдельного холивара)
0
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
04.07.2020, 11:49
Цитата Сообщение от RR-Zz Посмотреть сообщение
Уйти от форматированной строки.
А тут что?
Цитата Сообщение от RR-Zz Посмотреть сообщение
C++
1
2
3
log(L_TEST, L_TEST, "H%s", "W"); //4
 log(L_TEST, L_TEST, "H %c %s", 'W', "!"); //4 + 1
 log(L_TEST, L_TEST, "H %c %s %d", 'W', "!", 666); //4 + 2
0
0 / 0 / 0
Регистрация: 30.11.2015
Сообщений: 15
04.07.2020, 15:26  [ТС]
Пожалуйста, читайте внимательнее
Цитата Сообщение от RR-Zz Посмотреть сообщение
не городить форматированную строку для 3-х параметров, а потом еще одну такую же для вывода print
Цитата Сообщение от assemberist Посмотреть сообщение
Это тема отдельного холивара)
Когда нет толковых предложений, начинается именно это =)
0
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
04.07.2020, 18:33
Цитата Сообщение от RR-Zz Посмотреть сообщение
не городить форматированную строку для 3-х параметров
Ну ок, выкинул ты ее. А ты пробовал смотреть ассемблерный листинг? Знаешь сколько аргументов закидывается в стек каждый раз? специально для тебя листинги с твоим кодом и с формат-строкой.
Assembler
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# your code
main:
.LFB23:
    .cfi_startproc
    leal    4(%esp), %ecx   #,
    .cfi_def_cfa 1, 0
    andl    $-16, %esp  #,
    pushl   -4(%ecx)    #
    pushl   %ebp    #
    .cfi_escape 0x10,0x5,0x2,0x75,0
    movl    %esp, %ebp  #,
    pushl   %edi    #
    pushl   %esi    #
    pushl   %ebx    #
    .cfi_escape 0x10,0x7,0x2,0x75,0x7c
    .cfi_escape 0x10,0x6,0x2,0x75,0x78
    .cfi_escape 0x10,0x3,0x2,0x75,0x74
    call    __x86.get_pc_thunk.bx   #
    addl    $_GLOBAL_OFFSET_TABLE_, %ebx    # tmp82,
    pushl   %ecx    #
    .cfi_escape 0xf,0x3,0x75,0x70,0x6
    subl    $16, %esp   #,
# main.c:254:     log(); //0
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
# main.c:259:     log(L_TEST, "test"); //2
    leal    .LC2@GOTOFF(%ebx), %esi #, tmp84
# main.c:267:     log(L_TEST, L_TEST, "H %c %s", 'W', "!");         //4 + 1
    leal    .LC7@GOTOFF(%ebx), %edi #, tmp92
# main.c:254:     log(); //0
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $254    #
    call    logger_test #
# main.c:256:     log(L_TEST); //1
    addl    $40, %esp   #,
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $256    #
    call    logger_test #
# main.c:258:     log(L_TEST, L_TEST); //2
    addl    $40, %esp   #,
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $2  #
    pushl   $0  #
    pushl   $258    #
    call    logger_test #
# main.c:259:     log(L_TEST, "test"); //2
    addl    $40, %esp   #,
    pushl   $0  #
    pushl   %esi    # tmp84
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $5  #
    pushl   $0  #
    pushl   $259    #
    call    logger_test #
# main.c:261:     log(L_TEST, L_TEST, "test"); //3
    addl    $40, %esp   #,
    pushl   $0  #
    pushl   %esi    # tmp84
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $6  #
    pushl   $0  #
    pushl   $261    #
    call    logger_test #
# main.c:262:     log(L_TEST, "%s", "test");   //3
    addl    $40, %esp   #,
    leal    .LC3@GOTOFF(%ebx), %eax #, tmp87
    pushl   %esi    # tmp84
    pushl   %eax    # tmp87
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $9  #
    pushl   $0  #
    pushl   $262    #
    call    logger_test #
# main.c:264:     log(L_TEST, "%c %s", 't', "test"); //3 + 1
    addl    $44, %esp   #,
    leal    .LC4@GOTOFF(%ebx), %eax #, tmp89
    pushl   %esi    # tmp84
# main.c:266:     log(L_TEST, L_TEST, "H%s", "W");                  //4
    leal    .LC5@GOTOFF(%ebx), %esi #, tmp90
# main.c:264:     log(L_TEST, "%c %s", 't', "test"); //3 + 1
    pushl   $116    #
    pushl   %eax    # tmp89
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $11 #
    pushl   $0  #
    pushl   $264    #
    call    logger_test #
# main.c:266:     log(L_TEST, L_TEST, "H%s", "W");                  //4
    addl    $40, %esp   #,
    leal    .LC6@GOTOFF(%ebx), %eax #, tmp91
    pushl   %esi    # tmp90
    pushl   %eax    # tmp91
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $12 #
    pushl   $0  #
    pushl   $266    #
    call    logger_test #
# main.c:267:     log(L_TEST, L_TEST, "H %c %s", 'W', "!");         //4 + 1
    addl    $44, %esp   #,
    leal    .LC8@GOTOFF(%ebx), %eax #, tmp93
    pushl   %edi    # tmp92
    pushl   $87 #
    pushl   %eax    # tmp93
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $14 #
    pushl   $0  #
    pushl   $267    #
    call    logger_test #
# main.c:268:     log(L_TEST, L_TEST, "H %c %s %d", 'W', "!", 666); //4 + 2
    addl    $48, %esp   #,
    leal    .LC9@GOTOFF(%ebx), %eax #, tmp95
    pushl   $666    #
    pushl   %edi    # tmp92
    pushl   $87 #
    pushl   %eax    # tmp95
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $16 #
    pushl   $0  #
    pushl   $268    #
    call    logger_test #
# main.c:270:     log(L_TEST, L_TEST, NULL, "W");    //4 + E
    addl    $40, %esp   #,
    pushl   %esi    # tmp90
    pushl   $0  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $18 #
    pushl   $0  #
    pushl   $270    #
    call    logger_test #
# main.c:271:     log(L_TEST, L_TEST, NULL, "W", 1); //4 + 1 + E
    addl    $44, %esp   #,
    pushl   $1  #
    pushl   %esi    # tmp90
    pushl   $0  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $1  #
    pushl   $0  #
    pushl   $20 #
    pushl   $0  #
    pushl   $271    #
    call    logger_test #
# main.c:273:     log(LOGGER_NULL, LOGGER_NULL, NULL, "W", 1); //4N + 1 + E
    addl    $44, %esp   #,
    pushl   $1  #
    pushl   %esi    # tmp90
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $0  #
    pushl   $22 #
    pushl   $0  #
    pushl   $273    #
    call    logger_test #
    addl    $48, %esp   #,
# main.c:277: }
Assembler
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
# my code
 
main:
.LFB1:
    .cfi_startproc
    leal    4(%esp), %ecx   #,
    .cfi_def_cfa 1, 0
    andl    $-16, %esp  #,
    pushl   -4(%ecx)    #
    pushl   %ebp    #
    .cfi_escape 0x10,0x5,0x2,0x75,0
    movl    %esp, %ebp  #,
    pushl   %ebx    #
    pushl   %ecx    #
    .cfi_escape 0xf,0x3,0x75,0x78,0x6
    .cfi_escape 0x10,0x3,0x2,0x75,0x7c
    call    __x86.get_pc_thunk.bx   #
    addl    $_GLOBAL_OFFSET_TABLE_, %ebx    # tmp82,
# main.c:35:    logger("yes, it`s one string");
    subl    $12, %esp   #,
    leal    .LC2@GOTOFF(%ebx), %eax #, tmp85
    pushl   %eax    # tmp85
    call    logger  #
    addl    $16, %esp   #,
# main.c:36:     logger("qwe %s %i %s %v qwe\n", "hello", 3, "rtyu");
    leal    .LC3@GOTOFF(%ebx), %eax #, tmp86
    pushl   %eax    # tmp86
    pushl   $3  #
    leal    .LC4@GOTOFF(%ebx), %eax #, tmp87
    pushl   %eax    # tmp87
    leal    .LC5@GOTOFF(%ebx), %eax #, tmp88
    pushl   %eax    # tmp88
    call    logger  #
    addl    $16, %esp   #,
    movl    $0, %eax    #, _4
Цитата Сообщение от RR-Zz Посмотреть сообщение
сделать обязательным параметром L_1 и (полу)обязательным параметр L_2
Мне немного лень разбираться в твоем коде, 250 строк как-никак. Можешь словами объяснить зачем они нужны?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
04.07.2020, 20:04
Цитата Сообщение от assemberist Посмотреть сообщение
А ты пробовал смотреть ассемблерный листинг? Знаешь сколько аргументов закидывается в стек каждый раз?
Логгирование подразумевает запись в файл или хотя бы на экран. Это ОЧЕНЬ долгие операции (по машинным меркам). И от того, что вместо 10 параметров будет передаваться, скажем, 3, скорость работы изменится на какие-то миллионные доли процента

Цитата Сообщение от RR-Zz Посмотреть сообщение
Когда нет толковых предложений, начинается именно это =)
Когда изначально нет внятной постановки задачи, "это" тоже начинается. Ты написал длинный код и поставил задачу как "разберитесь в нём и сделайте, чтобы мне стало хорошо". Очевидно, что желающих разбираться в твоём коде не нашлось
0
0 / 0 / 0
Регистрация: 30.11.2015
Сообщений: 15
04.07.2020, 20:37  [ТС]
Давайте по порядку.

Цитата Сообщение от assemberist Посмотреть сообщение
специально для тебя листинги с твоим кодом и с формат-строкой
Во-первых, если вы пытаетесь аргументировать это ассемблерным видом, то привели бы две одинаковые функции в одинаковом количестве, одинаковыми параметрами, и одинаковым выводом.. на мой и на ваш манер. Иначе получается манипулирование фактами.

Цитата Сообщение от assemberist Посмотреть сообщение
Мне немного лень разбираться в твоем коде, 250 строк как-никак.
Во-вторых код там явно не на 250 строчек, а на 147. Если мы про первый говорим, который я изначально показывал
В-третьих он однотипный и большая из них часть это тестовый вывод.

Цитата Сообщение от assemberist Посмотреть сообщение
Можешь словами объяснить зачем они нужны?
Об этом стоило спрашивать, до того как вы начали мне предлагать свои решения.

Цитата Сообщение от Evg Посмотреть сообщение
Логгирование подразумевает запись в файл или хотя бы на экран. Это ОЧЕНЬ долгие операции (по машинным меркам). И от того, что вместо 10 параметров будет передаваться, скажем, 3, скорость работы изменится на какие-то миллионные доли процента
А я и не пытаюсь дорожить машинным временем, я забочусь об удобстве использования.

Цитата Сообщение от Evg Посмотреть сообщение
Когда изначально нет внятной постановки задачи
Извините конечно, но об этом я сказал сразу вот здесь
Цитата Сообщение от RR-Zz Посмотреть сообщение
Провел весь день, чтобы попытаться вызвать функцию с помощью макроса в зависимости от количества и типа переданных параметров.
И дал код для проведения экспериментов, а в нем уже был тот "API" который я пытался реализовать.
И вполне себе реализовал.

И последнее.
Предложить ТСу вещь Б, когда он точно уверен что ему нужна вещь А или на крайний случай а, но которая имитирует поведение первой.
Классика форумов.
Если Вы научились обходить форматированную строку указателями, это не значит что теперь это в каждой бочке затычка. Иногда внешний вид важнее, чем лишние такты.
0
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
04.07.2020, 23:49
Цитата Сообщение от RR-Zz Посмотреть сообщение
Предложить ТСу вещь Б, когда он точно уверен что ему нужна вещь А или на крайний случай а, но которая имитирует поведение первой.
ТС может быть уверен в чем угодно, а нам нужно четкое изложение задачи.
Цитата Сообщение от RR-Zz Посмотреть сообщение
Во-первых, Во-вторых, В-третьих
Тема катится в никуда. Давай спокойно обсудим вопросы если они еще остались. Если нет, то рады были помочь)
0
0 / 0 / 0
Регистрация: 30.11.2015
Сообщений: 15
05.07.2020, 00:24  [ТС]
Цитата Сообщение от assemberist Посмотреть сообщение
Давай спокойно обсудим вопросы если они еще остались.
Цитата Сообщение от RR-Zz Посмотреть сообщение
Этого можно избежать, если каждый вызов брать в #pragma
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wint-conversion"
log(1, 2); //2
log(1, "test");
#pragma GCC diagnostic pop

Сейчас пытаюсь, сделать так, чтобы эта конструкция вызывалась вместе с log();
Но способа пока найти не могу..
Только этот =)
Сам понимаю что это уже не возможно, но может и не достаточно осведомлен.

Добавлено через 32 минуты
Или вопрос поставить ребром.

Почему _Generic ругается на каст переменных?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
05.07.2020, 12:14
Цитата Сообщение от RR-Zz Посмотреть сообщение
А я и не пытаюсь дорожить машинным временем, я забочусь об удобстве использования
Я всего лишь пытался объяснить assemberist'у, что когда речь идёт о логгировании, то смотреть на скорость исполнения не нужно вообще. Правда мысль как-то невнятно написал

Цитата Сообщение от RR-Zz Посмотреть сообщение
Извините конечно, но об этом я сказал сразу вот здесь
То, что написано "здесь", принципиально ничем не отличается от миллионов других тем, начинающихся со слов "Облазил весь интернет и не нашёл, как решить мою проблему. Вот вам код на 100500 строк, исправьте мои ошибки"

Цитата Сообщение от RR-Zz Посмотреть сообщение
Предложить ТСу вещь Б, когда он точно уверен что ему нужна вещь А
Опять-таки это стандартное следствие невнятной постановки вопроса. Те, кто действительно могли бы тебе помочь, они просто не стали вникать в твой код, т.к. пришлось бы гадать на тему того, что же ты хочешь, а гадать мало кому хочется. Мне с ходу показалось, что здесь предполагаемая постановка задачи решается в корне неверно, и следовало бы просто воспользоваться vprintf'ом (см. пример в cin cout и fscan fprintf), но совершенно не хочется заниматься гаданиями и задавать сотню наводящих вопросов
0
656 / 409 / 76
Регистрация: 21.09.2008
Сообщений: 1,406
08.07.2020, 17:27
Цитата Сообщение от assemberist Посмотреть сообщение
Компилил на TDM-GCC 4.9.2
Доступна версия 9.2.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
08.07.2020, 17:27
Помогаю со студенческими работами здесь

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

Проверка переданных параметров
Здравствуйте! Собственно, есть класс и есть конструктор класса. Данными класса является массив int и кол-во элементов в нём (short)....

Обработчик параметров, переданных методом GET
$name=htmlspecialchars($_GET); $fp = fopen(&quot;$name&quot;, &quot;r&quot;); // Открываем файл в режиме чтения if ($fp) echo fpassthru($fp); else echo...

Обработка параметров переданных из формы
Есть ASP-страничка с формой. Данные по submit посылаются сюда же. Затем, среди всего прочего, имеет место быть вот такой код: &lt;% ......

Вывести сообщении в зависимости от переданных параметров
Написать batch файл. Проверять передаваемые параметры. Например, если введенное значение равно 1 выводить сообщение «1», если не равно «не...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru