Самый элегантный способ поделиться массивом C - PullRequest
5 голосов
/ 22 февраля 2012

Я должен вернуться к (встроенному) C через некоторое время с C ++, и у меня возникла следующая проблема:

У меня есть исходный модуль, который включается много раз, давайте назовем его utilities.h и utilities.c В нем у меня есть важный массив, давайте назовем его

#define IMPORTANT_ARRAY_LENGTH  10000
char important_array[IMPORTANT_ARRAY_LENGTH];

У меня есть много других функций в этом модуле utilities, и все они работают нормально.Однако в одном из других исходных файлов, назовем его worker.c, я должен использовать этот массив.Что такое «официальный», элегантный способ сделать это, не помещая extern char important_array[IMPORTANT_ARRAY_LENGTH] и определение макроса в worker.c?

Если я сделаю следующее:

утилиты.h

#ifndef _UTILITIES_H_
#define _UTILITIES_H_

#define IMPORTANT_ARRAY_LENGTH  10000
extern char important_array[IMPORTANT_ARRAY_LENGTH];

// ...

utilities.c

#ifndef _UTILITIES_C_
#define _UTILITIES_C_

#include "utilities.h"

char important_array[IMPORTANT_ARRAY_LENGTH];

// ...

worker.c

#include "utilities.h"
// ...
important_array[0] = 0;

, тогда мой массив будет неопределенным символом в worker.c.Если я не использую ключевое слово extern в utilities.h, то, конечно, это дублирующий символ.(Как ни странно, он компилируется только с предупреждением, и я могу видеть из файла компоновщика, что размер выделяется несколько раз.)

Действительно ли мне нужно объявить мой массив в worker.c?Я хочу сохранить все в чистоте и иметь все объявления только в одном месте: в заголовочном файле.И я хочу иметь определение макроса только один раз (это вторично, потому что я мог бы использовать const, но я хочу, чтобы препроцессор обрабатывал его, а не занимал место)

Ответы [ 4 ]

4 голосов
/ 22 февраля 2012

У вас есть канонический способ сделать это: иметь объявление extern в заголовочном файле и определить переменную в файле .c.

мой массив будет неопределенным символом в worker.c

Нет, не будет. Ваш код будет компилироваться и ссылаться просто отлично.

2 голосов
/ 22 февраля 2012

Я часто помещаю определение в заголовок (это осуждается, я знаю).Это держит определение и декларацию близко друг к другу, что является хорошей вещью.

/* file.c */
#define FILE_C 1
#include "file.h"

.

/* file.h */
#ifndef FILE_H
#define FILE_H 1

#define BIG_SIZE 13

#if FILE_C 
char the_array[BIG_SIZE];
#else
extern char the_array[BIG_SIZE];
#endif

#endif /* FlLE_H */

.

 /* other_file.c */
#include "file.h"

Нет риска сделатьэто неправильно: компоновщик будет жаловаться, если вы сделаете это неправильно.

Кстати, аналогичный способ сделать то же самое, но, возможно, немного более читабельный, это:

/* file.h */
#ifndef FILE_H
#define FILE_H 1

#if FILE_C
#define EXTERN /**/
#else
#define EXTERN extern
#endif

#define BIG_SIZE 13

EXTERN char the_array[BIG_SIZE];

...

#undef EXTERN
#endif /* FlLE_H */
1 голос
/ 22 февраля 2012

Создайте новую функцию в utilities.c, которая называется что-то вроде «get_important_array», которая просто возвращает указатель на массив и помещает прототип в utilities.h. После этого, когда вы разместите utilities.h в worker.c, вы получите доступ к важный_арритеру простым и организованным способом.

1 голос
/ 22 февраля 2012

Наличие одного объявления (extern...) в каждой единице перевода и ровно одного определения - самый элегантный способ сделать это.

Так что оставьте extern char important_array в заголовке и char important_array в одном из .c файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...