Форум программистов, компьютерный форум, киберфорум
Наши страницы

C для начинающих

Войти
Регистрация
Восстановить пароль
 
Pavel Kisliuk
22 / 22 / 7
Регистрация: 27.09.2015
Сообщений: 99
#1

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

21.09.2016, 19:06. Просмотров 796. Ответов 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
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Условная компиляция (с участием нескольких файлов) (C (СИ)):

Компиляция и сборка нескольких файлов исходного кода - C (СИ)
Имеется такая программа из книги Кернигана и Ритчи: #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; /*для atof()*/ #define MAXOP 100 /*...

EclipseC и условная компиляция - C (СИ)
Здравствуйте, уважаемые. С Си знаком мало, поэтому разобраться сам не смог... Прошу Вашей помощи. Есть исходники программы для...

Обработка нескольких файлов в цикле - C (СИ)
У меня вопрос. Можно ли в программе привязать к переменной файл, выполнять с ним действия, а потом закрыть его и к этой же переменной...

Считывание содержимого из нескольких файлов - C (СИ)
Доброго времени суток. Поискала в более ранних темах - не нашла. Суть проблемы вот в чем: у меня есть n текстовых файлов, которые надо...

Проект из нескольких файлов ( ошибка с <windows.h> ) - C (СИ)
Помогите разобраться с проектом из нескольких файлов. На паре написал вот такую програмку main.c #include &lt;stdio.h&gt; #include...

Тернарная условная операция - C (СИ)
Компилятор ругается на тернарные условные операции в 25 и 29 строке: 25 error: lvalue required as left operand of assignment 29 ...

5
HighPredator
5645 / 1961 / 372
Регистрация: 10.12.2010
Сообщений: 5,681
Записей в блоге: 3
22.09.2016, 08:12 #2
Познакомьтесь для начала вот с этим: http://www.cyberforum.ru/blogs/18334/blog100.html Потом, когда станет чуть яснее с чем вы имеете дело будем разбираться дальше.
1
Pavel Kisliuk
22 / 22 / 7
Регистрация: 27.09.2015
Сообщений: 99
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
5645 / 1961 / 372
Регистрация: 10.12.2010
Сообщений: 5,681
Записей в блоге: 3
22.09.2016, 10:49 #4
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Почти. Красивее и точнее было бы сделать так:
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
22 / 22 / 7
Регистрация: 27.09.2015
Сообщений: 99
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
5645 / 1961 / 372
Регистрация: 10.12.2010
Сообщений: 5,681
Записей в блоге: 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
Привет! Вот еще темы с ответами:

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

Компиляция нескольких файлов - C++
Создал проект на wxDevC++ таким образом: потом создал три файла в проекте: coordin.h #ifndef COORDIN_H_ #define COORDIN_H_...

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

Компиляция нескольких файлов - Matlab
Допустим запустил такую команду: mcc -m f1.m f2.m f3.m где f1-f3 это файлы-функции. Какая из этих трех функций будет...


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

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

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