Я думаю, что ваш дизайн потерпит неудачу, но я также не уверен, что другие ответы, которые я вижу, полностью связаны с более глубокими причинами.
Похоже, что вы пытаетесь использовать C для работы с общими типами, то, что всегда становится волосатым. Вы можете сделать это, если вы осторожны, но это нелегко, и в этом случае я сомневаюсь, стоит ли это того.
Более глубокая причина : Давайте предположим, что мы преодолели простые синтаксические (или чуть больше, чем синтаксические) проблемы. Ваш код показывает, что T10CNT содержит 20 int
, а T20CNT содержит 20 long
. На современных 64-битных машинах - кроме Win64 - sizeof(long) != sizeof(int)
. Поэтому код внутри вашей функции печати должен различать разыменование массивов int
и массивов long
. В C ++ есть правило, что вы не должны пытаться обрабатывать массивы полиморфно, и вот почему. Тип CMNCNT содержит 3 long
значений; отличается от чисел как структур T10CNT, так и T20CNT, хотя базовый тип массива совпадает с T20CNT.
Рекомендация по стилю : я настоятельно рекомендую избегать подчеркивания в именах. В общем, имена, начинающиеся с подчеркивания, зарезервированы для реализации и для использования в качестве макросов. Макросы не имеют никакого отношения к области видимости; если реализация определяет макрос _cnt, это разрушит ваш код. Есть нюансы того, какие имена зарезервированы; Я не собираюсь вдаваться в эти нюансы. Гораздо проще думать «имена, начинающиеся с подчеркивания, зарезервированы», и это избавит вас от неприятностей.
Предложение по стилю : Ваша функция печати возвращает успех безоговорочно. Это не имеет смысла; Ваша функция не должна ничего возвращать, чтобы вызывающий не проверял ее на успех или неудачу (так как она никогда не может потерпеть неудачу). Внимательный кодер, который замечает, что функция возвращает статус, всегда проверяет статус возврата и имеет код обработки ошибок. Этот код никогда не будет выполнен, поэтому он мертв, но кому-либо (или компилятору) сложно это определить.
Поверхностное исправление : Временно мы можем предположить, что вы можете рассматривать int
и long
как синонимы; но вы должны избавиться от привычки думать, что они являются синонимами. Аргумент void *
является правильным способом сказать "эта функция принимает указатель неопределенного типа". Однако внутри функции вам необходимо преобразовать из void *
в определенный тип, прежде чем выполнять индексацию.
typedef struct _CMNCNT
{
long count[3];
} CMNCNT;
static void printCommonStatistics(const void *data, size_t nelem, size_t elemsize)
{
int i;
for (i = 0; i < nelem; i++)
{
const CMNCNT *cmncnt = (const CMNCNT *)((const char *)data + (i * elemsize));
fprintf(stdout,"STATISTICS_INP: %ld\n", cmncnt->count[0]);
fprintf(stdout,"STATISTICS_OUT: %ld\n", cmncnt->count[1]);
fprintf(stdout,"STATISTICS_ERR: %ld\n", cmncnt->count[2]);
}
}
(мне тоже нравится идея файлового потока с именем stout
. Предложение : используйте cut'n'paste для реального исходного кода - это безопаснее! Я обычно использую "sed 's/^/ /' file.c
"чтобы подготовить код для вырезки и вставки в SO-ответ.)
Что делает эта линия приведения? Я рад, что ты спросил ...
- Первая операция - преобразовать
const void *
в const char *
; это позволяет вам выполнять операции с байтовым размером по адресу. Во времена, предшествующие стандарту C, char *
использовался вместо void *
в качестве универсального механизма адресации.
- Следующая операция добавляет правильное количество байтов, чтобы добраться до начала
i
-го элемента массива объектов размером elemsize
.
- Затем второй актер сообщает компилятору «доверяй мне - я знаю, что я делаю» и «воспринимаю этот адрес как адрес структуры CMNCNT».
Оттуда код достаточно прост. Обратите внимание, что поскольку структура CMNCNT содержит значение long
, я использовал %ld
, чтобы сказать правду fprintf()
.
Поскольку вы не собираетесь изменять данные в этой функции, неплохо было бы использовать квалификатор const
, как я.
Обратите внимание, что если вы хотите быть верным sizeof(long) != sizeof(int)
, то вам нужно два отдельных блока кода (я бы предложил отдельные функции) для работы с массивом int
и массивом long
Типы конструкций.