计算C中静态数组初始化的元素数

时间:2016-04-18 17:10:14

标签: c c-preprocessor variadic-macros

有以下代码(C99):

#define MAX_ALLOCATIONS 2

#if !defined(ALLOCATIONS)
  #define ALLOCATIONS {{1, 0, 0, 64},{1, 0, 0, 32}}
#endif

struct allocation
{
  int thread_count_;

  int node_run_;

  int node_alloc_;

  int size_alloc_;
};

static struct allocation allocations[MAX_ALLOCATIONS] = ALLOCATIONS;

编译此代码时,可以传递以下内容: -D'ALLOCATIONS={{1, 0, 0, 8},{1, 0, 0, 16},{1, 0, 0, 4}}'

是否有可能获得一个可以计算分配数量的宏?例如,它应该在 {{1, 0, 0, 8},{1, 0, 0, 16},{1, 0, 0, 4}} 时计算3。这将允许在上面的代码中摆脱MAX_ALLOCATIONS。 是的,简单的方法是将 -DMAX_ALLOCATIONS=3 单独传递给 -D'ALLOCATIONS={{1, 0, 0, 8},{1, 0, 0, 16},{1, 0, 0, 4}}' ,但这对用户来说容易出错。

谢谢

2 个答案:

答案 0 :(得分:1)

定义数组MAX_ALLOCATIONS时,您无需使用allocations

您需要做的就是将ALLOCATIONS定义为您的元素,并自动确定数组的大小。

当您需要代码中该数组的大小时,使用此宏,它将给出数组allocations中的元素数量:

#define MAX_ALLOCATIONS (sizeof(allocations)/sizeof(allocations[0]))

这是一个常数值。

答案 1 :(得分:0)

  

是否有可能得到一个宏。

是的......也许是宏,但肯定是以编程方式。例如:

(在Linux上编译> gcc -o test -D'ALLOCATIONS =“{{1,0,0,0},{1,0,0,16},{1,0,0,4} }''* .c ):

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>   // malloc()

typedef struct allocation_s
   {
   int thread_count_;
   int node_run_;
   int node_alloc_;
   int size_alloc_;
   } allocation_t;

/** **************************************************************************
* Print allocation records.
*/
int PrintRecords(
      allocation_t *I__allocations,
      int           I__elements
      )
   {
   int rCode = 0;
   int index;

   for(index=0; index < I__elements; ++index, ++I__allocations)
      printf("{%d, %d, %d, %d}\n",
         I__allocations->thread_count_,
         I__allocations->node_run_,
         I__allocations->node_alloc_,
         I__allocations->size_alloc_
         );

   return(rCode);
   }

/** **************************************************************************
* Read a record from allocation string.
*/
int ReadRecord(
      char          *I__string,
      char         **_O_next,
      allocation_t  *_O_record
      )
   {
   int   rCode = 0;
   char *cp    = I__string;
   allocation_t record;

   while(*cp && (' ' == *cp || ',' == *cp))
      ++cp;

   if('{' != *cp)
      {
     rCode=EINVAL;
      fprintf(stderr, "[1]Allocations parsing error.\n");
      goto CLEANUP;
      }

   while(*cp && (' ' == *cp || '{' == *cp))
      ++cp;

   record.thread_count_ = strtoul(cp, &cp, 10);
   while(*cp && (' ' == *cp || ',' == *cp))
      ++cp;

   record.node_run_ = strtoul(cp, &cp, 10);
   while(*cp && (' ' == *cp || ',' == *cp))
      ++cp;

   record.node_alloc_ = strtoul(cp, &cp, 10);
   while(*cp && (' ' == *cp || ',' == *cp))
      ++cp;

   record.size_alloc_ = strtoul(cp, &cp, 10);
   cp=strchr(cp, '}');
   if(!cp)
      {
      rCode=EINVAL;
      fprintf(stderr, "[2]Allocations parsing error.\n");
      goto CLEANUP;
      }

   ++cp;

//RESULTS:

   if(_O_record)
      memcpy(_O_record, &record, sizeof(*_O_record));

   if(_O_next)
      *_O_next = (char *)cp;

CLEANUP:

   return(rCode);   
   };   

/** **************************************************************************
* Program start.
*/
int main(
      int   I__argC,
      char *I__argV[]
      )
   {
   int rCode=0;
   char *rawDataString = ALLOCATIONS;
   char *cp = rawDataString;
   int   elements = 0;
   allocation_t *allocations_A = NULL;
   allocation_t *allocationsPtr;
   int   index;

   if('{' != *cp)
      {
      fprintf(stderr, "Allocations parsing error.\n");
      goto CLEANUP;
      }

   /** -----------------------------------------------------------------------
   * Count the elements.
   */
   do {
      rCode=ReadRecord(cp, &cp, NULL);
      ++elements;         
      } while(!rCode && ',' == *cp);  
   if(rCode)
      {
      fprintf(stderr, "ReadRecord() reports: %d\n", rCode);
      goto CLEANUP;
      }

   /** -----------------------------------------------------------------------
   * Allocate the array.
   */
   errno=0;
   allocations_A = malloc(sizeof(*allocations_A) * elements);
   if(!allocations_A)
      {
      rCode=errno;
      fprintf(stderr, "malloc() failed: errno:[%d] %s\n", rCode, strerror(rCode));
      goto CLEANUP;
      }

   /** -----------------------------------------------------------------------
   * Initialize the array.
   */
   cp = rawDataString;
   allocationsPtr = allocations_A;
   for(index=0; index < elements; ++index)
      {
      rCode=ReadRecord(cp, &cp, allocationsPtr++);
       if(rCode)
         {
         fprintf(stderr, "ReadRecord() reports: %d\n", rCode);
         goto CLEANUP;
         }
      }   

   /** -----------------------------------------------------------------------
   * Print the array.
   */
   PrintRecords(allocations_A, elements);

CLEANUP:

   return(rCode);   
   } 

示例输出:

{1, 0, 0, 8}
{1, 0, 0, 16}
{1, 0, 0, 4}