Apparently I have a fundamental misunderstanding of how macros work. I thought a macro just caused the preprocessor to replace the @define
d macro with the replacement text. But apparently that's not always the case. My code follows:
TstBasInc.h
#pragma once
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <time.h>
// copy macro
#define Cpy(ToVar, FrmVar) do { \
errno = strncpy_s(ToVar, sizeof(ToVar), FrmVar, _TRUNCATE); \
if (errno == STRUNCATE) \
fprintf(stderr, "string '%s' was truncated to '%s'\n", FrmVar, ToVar); \
} while(0);
// clear numeric array macro
#define ClrNumArr(ArrNam, ArrCnt) \
for (s = 0; s < ArrCnt; s++) \
ArrNam[s] = 0;
uint32_t s; // subscript
typedef struct {
short C;
short YY;
short MM;
short DD;
} SysDat;
TstMacCmpErr:
#include "stdafx.h"
#include "TstBasInc.h" // test basic include file
#define ARRCNT 3
int main()
{
char Cnd = 'E'; // define to use 'else' path
char ToVar[7 + 1]; // Cpy To-Variable
int IntArr[ARRCNT]; // integer array
Cpy(ToVar, "short") // compiles with or without the semi-colon
if (Cnd != 'E')
// Cpy(ToVar, "short string"); // won't compile: illegal else without matching if
Cpy(ToVar, "short string") // will compile
else
Cpy(ToVar, "extra long string"); // compiles with or without the semi-colon
// the following code shows how I thought the macro would expand to
{ \
errno = strncpy_s(ToVar, sizeof(ToVar), "short str", _TRUNCATE); \
if (errno == STRUNCATE) \
fprintf(stderr, "string '%s' was truncated to '%s'\n", "short str", ToVar);; \
}
if (Cnd == 'E') {
ClrNumArr(IntArr, ARRCNT) // compiles with or without the semi-colon
printf("intarr[0] = %d\n", IntArr[0]);
}
else
printf("intarr[0] is garbage\n");
return 0;
}
The results follow:
string 'extra long string' was truncated to 'extra l'
string 'short str' was truncated to 'short s'
intarr[0] = 0;
As the comments say, when I have a semi-colon after Cpy(ToVar, "short string");
it won't even compile because I get an "C2181 illegal else without matching if"
error. As you see, I tried adding a do-while in the macro as suggested in this post, but it didn't make any difference. When the macro code is copied directly (even without the do-while) that code works okay. I would have thought just adding the braces in the macro would have fixed the problem but it didn't. It must have something to do with the Cpy
ending in an if
because the ClrNumArr
macro compiles with or without the semi-colon. So can someone tell me why the Cpy
macro doesn't just replace the text? I must be missing something simple.
I'm using VS 2015 Community Edition Update 1.
Edit: I documented the problem and isolated it to (I think) the if
statement in the Cpy
macro. Still nobody has explained why the macro didn't expand the way I thought it should. That should have been the title of the post, as that's my question more than the problem with the semi-colon, which I now have a solution for.