Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
Pavel Kisliuk
24 / 24 / 17
Регистрация: 27.09.2015
Сообщений: 106
#1

Условная компиляция (с участием нескольких файлов)

21.09.2016, 19:06. Просмотров 875. Ответов 5
Метки нет (Все метки)

Добрый день. Мне нужно выполнить задание, а для этого нужно понять условную компиляцию, которая, честно говоря, не совсем понятна. На данный момент есть три файла - с main(), header с прототипами и .c с самими функциями.

header имеет следующие прототипы:
C
1
2
3
4
5
void fill_In_Array(int *const Array, const size_t N);
 
void fill_In_Array(double *const Array, const size_t N);
 
void fill_In_Array(char *const Array, const size_t N);
Его .c файл раскрывает эти функции (не спрашивайте почему я так заполняю массив char - такое задание).
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void fill_In_Array(int *const Array, const size_t N)
{
    for (size_t i = 0; i < N; i++) {
        Array[i] = rand();
    }
}
 
void fill_In_Array(double *const Array, const size_t N)
{
    for (size_t i = 0; i < N; i++) {
        Array[i] = rand();
    }
}
 
void fill_In_Array(char *const Array, const size_t N)
{
    for (size_t i = 0; i < (N - 1); i++) {
        Array[i] = 32 + rand() % 94;
    }
}
Итак, в .c файле нужно описать функции, при этом функции необходимо написать для работы с массивом целых, действительных и символьных значений. (Для каждого типа написать отдельную функцию) .

Потом в header нужно:
а) описать прототипы всех функций; (уже описаны)
б) сделать проверку определена ли константа, указывающая на тип данных ( #ifdef INTEGER )
в ) создать обобщающие имена функции , которым будет определена функция соответствующего типа в зависимости от константы , указанной в файле prog.cpp . (# define show ShowInt )

В функции же, где main() нужно сделать следующее:
а) в функции main вызвать все функции через переозначеные( обобщенные ) имена из файла function.h ( show ( ))
б) определить константу , которая указывает какой тип данных будет использоваться . Например INTEGER - целые данные, CHAR - символьные DOUBLE - настоящие. (# define INTEGER )
Имя функциям нужно давать так , чтобы они отвечали своей сути . Например функция для вывода значений массива целых чисел на консоль - ShowArrayInt (). А, когда переопределяем функцию с помощью # define то нужно давать общее имя. Например # define ShowArray ShowArrayInt

Я так понимаю, что при помощи условной компиляции я должен сделать возможным вызов функции по определенному типу данных, однако как именно это сделать (программа, кстати, должна быть в трех разных файлах) я не могу понять, у Дейтла и Праты эти темы поверхностно и я не догоняю. Просьба помочь.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.09.2016, 19:06
Ответы с готовыми решениями:

Компиляция и сборка нескольких файлов исходного кода
Имеется такая программа из книги Кернигана и Ритчи: #include &lt;stdio.h&gt;...

EclipseC и условная компиляция
Здравствуйте, уважаемые. С Си знаком мало, поэтому разобраться сам не...

Считывание содержимого из нескольких файлов
Доброго времени суток. Поискала в более ранних темах - не нашла. Суть...

Обработка нескольких файлов в цикле
У меня вопрос. Можно ли в программе привязать к переменной файл, выполнять с...

Проект из нескольких файлов ( ошибка с <windows.h> )
Помогите разобраться с проектом из нескольких файлов. На паре написал вот...

5
HighPredator
5679 / 1998 / 721
Регистрация: 10.12.2010
Сообщений: 5,750
Записей в блоге: 3
22.09.2016, 08:12 #2
Познакомьтесь для начала вот с этим: http://www.cyberforum.ru/blogs/18334/blog100.html Потом, когда станет чуть яснее с чем вы имеете дело будем разбираться дальше.
1
Pavel Kisliuk
24 / 24 / 17
Регистрация: 27.09.2015
Сообщений: 106
22.09.2016, 10:08  [ТС] #3
HighPredator, ну, я вроде как примерно понимаю, но давайте по порядку, если Вам не сложно.

В header-файле мне нужно: "сделать проверку определена ли константа, указывающая на тип данных ( #ifdef INTEGER )". То есть я должен сделать следующее (как я понимаю).
C
1
2
3
4
5
6
7
8
9
10
11
#ifdef INTEGER
void fill_In_Array(int *const Array, const size_t N);
#endif
 
#ifdef DOUBLE
void fill_In_Array(double *const Array, const size_t N);
#endif
 
 #ifdef CHAR
void fill_In_Array(char *const Array, const size_t N);
#endif
Тут все верно?
0
HighPredator
5679 / 1998 / 721
Регистрация: 10.12.2010
Сообщений: 5,750
Записей в блоге: 3
22.09.2016, 10:49 #4
Лучший ответ Сообщение было отмечено Pavel Kisliuk как решение

Решение

Почти. Красивее и точнее было бы сделать так:
C
1
2
3
4
5
6
7
8
9
#if defined(INTEGER)
void fill_In_Array(int *const Array, const size_t N);
#elif defined(DOUBLE)
void fill_In_Array(double *const Array, const size_t N);
#elif defined(CHAR)
void fill_In_Array(char *const Array, const size_t N);
#else
#error One of the defines is required
#endif
Но лично я бы сделал так:
C
1
2
3
4
5
6
7
8
9
10
11
#if defined(INTEGER)
#define ARG_TYPE int
#elif defined(DOUBLE)
#define ARG_TYPE double
#elif defined(CHAR)
#define ARG_TYPE char
#else
#error Either INTEGER or DOUBLE or CHAR must be specified
#endif
 
void fill_in_array(ARG_TYPE* const Array, const size_t N);
Объясню почему: чтобы напрямую влиять на реализацию и не тащить директивы препроцессора в модуль, где реализована функция. В вашем виде это реально, потому что формально заполнение массива не кардинально меняет на реализацию функции в зависимости от типа данных. Собственно поэтому можно сделать так. Покажу на примере использования такой техники. Пусть у нас есть заголовочный файл func.h следующего вида:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef FUNC_H
#define FUNC_H
 
#if defined(INTEGER)
  #define ARG_TYPE int
#elif defined(DOUBLE)
  #define ARG_TYPE double
#elif defined(CHAR)
  #define ARG_TYPE char
#else
  #error Either INTEGER or DOUBLE or CHAR must be specified
#endif
 
void test(const ARG_TYPE* const arg);
 
#endif
и собственно модуль, в котором есть реализация данной функции func.c:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
#include "func.h"
 
static const char* AssumeTypeOnSize(const size_t typeSize)
{
  switch (typeSize)
  {
    case 1: return "char";
    case 4: return "int";
    case 8: return "double";
    default: return "unknown";
  }
}
 
void test(const ARG_TYPE* const arg)
{
  size_t argSize = sizeof(*arg);
  
  printf("Size of argument type is %lu, assumed type is '%s'\n",
      argSize, AssumeTypeOnSize(argSize));
}
То тогда, мы будем иметь возможность с помощью этих директив препроцессора собрать две "разные" программы, которые будут "по-разному" работать. Пусть программа №1 выглядит так:
C
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
#include "func.h"
 
int main(void)
{
  double a = 4.0;
  test(&a);
  return 0;
}
и собирается, с помощью мейкфайла, в котором имеется нужная директива препроцессора:
Код
CC = gcc
CFLAGS = -Wstrict-aliasing -std=c89 -pedantic -Wall -Wextra -Werror -O0 -DDOUBLE
EXECUTABLE = test_c

all: clean compile link

clean:
	rm -f *.o
	rm -f $(EXECUTABLE)
	
compile: main.o func.o
	
main.o: main.c
	$(CC) -c $(CFLAGS) main.c -o $@
	
func.o: func.c
	$(CC) -c $(CFLAGS) func.c -o $@
	
link: main.o func.o
	$(CC) main.o func.o -o $(EXECUTABLE)
При запуске будет выведено (если платформа как у меня на тесте):
Код
Size of argument type is 8, assumed type is 'double'
Аналогично для другой программы:
C
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
#include "func.h"
 
int main(void)
{
  int a = 4;
  test(&a);
  return 0;
}
Код
CC = gcc
CFLAGS = -Wstrict-aliasing -std=c89 -pedantic -Wall -Wextra -Werror -O0 -DINTEGER
EXECUTABLE = test_c

all: clean compile link

clean:
	rm -f *.o
	rm -f $(EXECUTABLE)
	
compile: main.o func.o
	
main.o: main.c
	$(CC) -c $(CFLAGS) main.c -o $@
	
func.o: func.c
	$(CC) -c $(CFLAGS) func.c -o $@
	
link: main.o func.o
	$(CC) main.o func.o -o $(EXECUTABLE)
будет выведено:
Код
Size of argument type is 4, assumed type is 'int'
Вот такая штука.
2
Pavel Kisliuk
24 / 24 / 17
Регистрация: 27.09.2015
Сообщений: 106
22.09.2016, 20:33  [ТС] #5
HighPredator, колоссально Вам благодарен, очень здорово! Однако, теперь у меня есть следующий код:

Файл Source.c, где находится main()
C
1
2
3
4
5
6
7
8
9
10
11
12
#define _CRT_SECURE_NO_WARNINGS
#define DOUBLE
#include <stdlib.h>
#include <time.h>
 
int main()
{
    srand((int)time(NULL));
    //---------------------------------------------------
    
    return 0;
}
Файл Function.h, где описан прототип функции и условная компиляция.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
#include <stdio.h>
#include <stdbool.h>
 
#if defined(INTEGER)
#define TYPE_OF_ARGUMENT int
#elif defined(DOUBLE)
#define TYPE_OF_ARGUMENT double
#elif defined(CHAR)
#define TYPE_OF_ARGUMENT char
#else
#error Either INTEGER or DOUBLE or CHAR must be specified
#endif
 
void fill_In_Array(TYPE_OF_ARGUMENT *const Array, const size_t N);
Файл Function.c, где реализована функция
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _CRT_SECURE_NO_WARNINGS
#define SIZE_OF_STRING 256
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
 
#include "Function.h"
 
void fill_In_Array(TYPE_OF_ARGUMENT *const Array, const size_t N)
{
    for (size_t i = 0; i < N; i++) {
        Array[i] = rand();
    }
}
Однако, несмотря на то, что в Source.c я во второй строчке сделал #define DOUBLE, компилятор в файлах Function.h и Function.c ругается на TYPE_OF_ARGUMENT и пишет, что #error: Either INTEGER or DOUBLE or CHAR must be specified

Где я делаю ошибку?
0
HighPredator
5679 / 1998 / 721
Регистрация: 10.12.2010
Сообщений: 5,750
Записей в блоге: 3
22.09.2016, 22:34 #6
Pavel Kisliuk, вам нужно, чтобы директива попала на вход препроцессору для обоих файлов. Сейчас у вас ошибка потому, что вы задали дефайн для мейна, но не для Source.c. Обратите внимание, в моих примерах дефайны эти вообще не задаются -- управление происходит извне исходного кода. Если вы хотите сделать также, то вам нужно подать этот дефайн через настройки вашей IDE.
1
22.09.2016, 22:34
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.09.2016, 22:34

Тернарная условная операция
Компилятор ругается на тернарные условные операции в 25 и 29 строке: 25 ...

Компиляция нескольких файлов
Здравствуйте, есть программа состоящая из 4 cpp, необходимо ее собрать,...

Компиляция нескольких файлов
Написать скрипт, который компилирует заданные файлы и передает на исполнение....


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru