• C

Why C language multi-line #define command failed when I use '\'

Hi,

I  have a struct  S_STYH defined by a multi-line #define command as follows:

#define PUBLIC_STYH                                     \
  char          eyecat[8];                              \
  t_styctx      *styctx;                                \
  t_stydel      *stydel;                                \
  char          *unused_1;                              \
  t_ssdrvex2k   *ssdrvex2k;                             \
  t_ssdrvhtm    *ssdrvhtm;                              \
  t_ssdrvpdf    *ssdrvpdf;                              \
  t_ssdrvps     *ssdrvps;                               \
  Uchar         *nlsBuf;   /* NLS work buffer */        \
  long          nlsBufLen; /* Length of nlsBuf */       \
  t_ssencodeURL *encodeURL;                             \
  t_sscb        styfuns;                                \
  t_stycommons  commons;                                \
  t_ssdrvr      driverInfo;                             \
  t_ssdrvwin    *ssdrvwin;                              \
  t_ssdrvxml    *ssdrvxml;                              \
  t_avlinsert   *avl_insert;                            \
  t_avlcount    *avl_count;                             \
  t_avlcreate   *avl_create;                            \
  t_avlfind     *avl_find;                              \
  t_avlfree     *avl_free;                              \
  union u_drvp  drvp;  /* local statics for a driver */ \
  t_getBackColor *getBackColor;                         \
  R1H           r1h;        /* R1 context */            \
  BOOL_         is_EBCDIC;  /* EBCDIC platform */       \
  t_getDrillArgValue *getDrillArgValue;                 \
  t_cbh         *cbh;                                   \
  Uchar         *utf8Buf;  /* NLS work buffer */        \
  long          utf8BufLen;                             \
  SS_NLSCharTab *nlsCharTab;                            \
  t_intlcmi     *intlcmi;  /* NLS handle */             \
  Uchar         *htmlTrt;   /* TRT for HTML encoding */ \
  t_ssdrvdhtm    *ssdrvdhtm;                            \
  Uchar         *nzapBuf;  /* NLS work buffer */        \
  long          nzapBufLen; /* Length of nlsBuf */      \
  char          *valueBuf;   /* Buffer for field val */ \
  char          *valueBuf2;  /* Buffer for field val */ \
  char          *urlBuf;     /* Buf. for encoded URL */ \
  t_bufCreate   *bufCreate;  /* Generic line buffer  */ \
  t_bufRealloc  *bufRealloc; /* Realloc line buffer  */ \
  t_bufFree     *bufFree;    /* Free line buffer     */
 
/*--- class STYH ---*/
struct  S_STYH {
  PUBLIC_STYH
};

Now I want to add the following new fields into struct  S_STYH:
long          grWidth;                                                          
long          grHeight;                              
long          TwipHeight;                            
long          TwipWidth;                              
char          fileName[256];

To do this, I add these fields directly at the end of the above multi-line #define command as follows:
#define PUBLIC_STYH                                     \
  char          eyecat[8];                              \
  t_styctx      *styctx;                                \
  t_stydel      *stydel;                                \
  char          *unused_1;                              \
  t_ssdrvex2k   *ssdrvex2k;                             \
  t_ssdrvhtm    *ssdrvhtm;                              \
  t_ssdrvpdf    *ssdrvpdf;                              \
  t_ssdrvps     *ssdrvps;                               \
  Uchar         *nlsBuf;   /* NLS work buffer */        \
  long          nlsBufLen; /* Length of nlsBuf */       \
  t_ssencodeURL *encodeURL;                             \
  t_sscb        styfuns;                                \
  t_stycommons  commons;                                \
  t_ssdrvr      driverInfo;                             \
  t_ssdrvwin    *ssdrvwin;                              \
  t_ssdrvxml    *ssdrvxml;                              \
  t_avlinsert   *avl_insert;                            \
  t_avlcount    *avl_count;                             \
  t_avlcreate   *avl_create;                            \
  t_avlfind     *avl_find;                              \
  t_avlfree     *avl_free;                              \
  union u_drvp  drvp;  /* local statics for a driver */ \
  t_getBackColor *getBackColor;                         \
  R1H           r1h;        /* R1 context */            \
  BOOL_         is_EBCDIC;  /* EBCDIC platform */       \
  t_getDrillArgValue *getDrillArgValue;                 \
  t_cbh         *cbh;                                   \
  Uchar         *utf8Buf;  /* NLS work buffer */        \
  long          utf8BufLen;                             \
  SS_NLSCharTab *nlsCharTab;                            \
  t_intlcmi     *intlcmi;  /* NLS handle */             \
  Uchar         *htmlTrt;   /* TRT for HTML encoding */ \
  t_ssdrvdhtm    *ssdrvdhtm;                            \
  Uchar         *nzapBuf;  /* NLS work buffer */        \
  long          nzapBufLen; /* Length of nlsBuf */      \
  char          *valueBuf;   /* Buffer for field val */ \
  char          *valueBuf2;  /* Buffer for field val */ \
  char          *urlBuf;     /* Buf. for encoded URL */ \
  t_bufCreate   *bufCreate;  /* Generic line buffer  */ \
  t_bufRealloc  *bufRealloc; /* Realloc line buffer  */ \
  t_bufFree     *bufFree;    /* Free line buffer     */ \
  long          grWidth;                                \                          
  long          grHeight;                               \
  long          TwipHeight;                           \
  long          TwipWidth;                            \                            
  char          fileName[256];    

But I got a compile error: "C2017: illegal escape sequence".  I also noticed the following: when I only add any one of the five new fields, I got no compile errors. However, whenever I add more than one new field, I immediately got the same compile error. It seems that there could be a limit on the maximum number of lines used in a multi-line #define command, but I find no such restrictions in my C books.

Although I think I may have a work-around to this problem, that is to simply create a new sub-structure under struct  S_STYH, but that is not what I really want to do, also I want to know what causes the problem.

Could you please help me out?

Thank you in advance for your help!

Starkman


starkmanAsked:
Who is Participating?
 
pulupulConnect With a Mentor Commented:
Firs of all, I would NEVER do such a big define. To track a compiler error caused by that define could lead to headache.
Said that, in the code you pasted there are a lot of spaces after the \ character that follows long grWidth;
Remember that for \ to work in a define, it must be last character in the line, being the only character that follows it the new line character. In your code, you should remove all the spaces after the \ characters.
This is because what \ does is to escape the new line character, so that the preprocessor "sees" all the lines as only one line. If there are spaces (or tab characters, or any other characters) behind the \ character, what is being scaped is the space right after it, and not the new line character, so the effect desired is not achieved.
Hope it helps.
0
 
grg99Commented:
It's not a good idea to use complex #defines or macros.

#define's are hard to debug because almost ANYTHING can go after #define XXX, there's no syntax checking at all.

You could try looking at the preprocessor output, usually the cpp command lets you see this.   That will often give you a hint as to what the #define is really doing, altho you'll also get a headache looking at all that output.

As otehrs have suggested, it's better to use something with a bit more syntax checking, like a bunch of sub-structs.  

0
 
jkrCommented:
I agree to all that was said here, but basically your problems stem from the comments (/* ... */) in your big #define statement.
0
Improve Your Query Performance Tuning

In this FREE six-day email course, you'll learn from Janis Griffin, Database Performance Evangelist. She'll teach 12 steps that you can use to optimize your queries as much as possible and see measurable results in your work. Get started today!

 
ankuratvbConnect With a Mentor Commented:
It works fine on my compiler(TurboC++ 3.0)

AT the end of the line,
>> long          grWidth;                                \

There was some extra whitespace after the \ which was causing the illegal escape seq. error.

Just realign the last few lines a bit and you'll be fine.

As long as your multi-line comments dont nest,those shouldnt give you an error.
0
 
JugglerWConnect With a Mentor Commented:
Just select follwong lines of your code in your browser and you can easily see that the
\ at the lines grWidth and TwipWidth are followed by many spaces. Just remove them as the other experts above have suggested.

 t_bufFree     *bufFree;    /* Free line buffer     */ \
  long          grWidth;                                \                          
  long          grHeight;                               \
  long          TwipHeight;                           \
  long          TwipWidth;                            \                            
  char          fileName[256];    

0
 
frankbairdCommented:
C has a mechanism for doing pretty much what you're looking for. It's called typedef.

typedef struct _s_styh
{
   char          eyecat[8];
   t_styctx      *styctx;
   t_stydel      *stydel;
   .
   .
   .
   char          fileName[256];
} s_styh;

To declare a struct of this type you then use
s_styh my_struct;

You can then use my_struct in your program, for example
my_struct.nlsBufLen = 128;

If you need this declaration in several places in your program, put it in a header file and include it.
#include "s_styh.h"
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.