Definition of macros

Posted on 2000-04-08
Last Modified: 2012-08-13
I have a macro that clears a static array , defined like that :

#define clear(x) ZeroMemory(x,sizeof(x))

I also have one that clears a dynamic array :

#define cleard(x,y) ZeroMemory(x,y)

To increase performace of my application , I started to convert arrays to dynamic . When clear is used to a dynamic array , it clears only the 4 bytes of it ( sizeof(dyn.array) = size of its pointer )

I saw in the help file that i can use the sizeof() operator in conditionals ( #if , #elif etc )
My question is : How can I redefine clear() so it checks if the size of the array is 4 , and if so , generate a compiler-time error (with #error)

Thanks .
Question by:WxW
  • 4
  • 4
  • 3
  • +1
LVL 22

Expert Comment

ID: 2695923
I wouldn't recommend it.

If you wrote the dynamic array, add a clear member function to it.  (Although clearing an array with 0's is not always a safe thing to do, like if it is an array of classes.)   You might be better of using a default constructor to initialize all the items.  This will 0 the built-in types.

If you are using the STL array class (vector), you can use the clear() function to delete all the items in the array and then use the resize() function to add default constructed items to the array.

You will be much much better of with that sort of approach.

Author Comment

ID: 2695940
The array is not a STL array

Just like char* xx = new char[1000];

I talk only for arrays with char[] ( buffers )

Expert Comment

ID: 2695945
if you don't take nietod's comment

then if you are using a char array why don't you use
clear(x) ZeroMemory(x,sizeof(char)*strlen(x))

or if you use difrrent array's write a func GetSize(...) that will get you the size of your object

and then use clear(x) ZeroMemory(x,GetSize(...))


Author Comment

ID: 2695968
ntdragon : strlen() wont work , 'cause the array might not be full .

How can GetSize get the size of the object ?
LVL 22

Expert Comment

ID: 2695978
You could do

#define cleard(x,y) ZeroMemory(x*sizeof(*y())

but honestly, I don't think I am doing you any favor...  I would strongly consider using array classes.
LVL 22

Expert Comment

ID: 2695979
Opps I got a parenthesis wrong.

#define cleard(x,y) ZeroMemory(x*sizeof(*y))
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

LVL 10

Expert Comment

ID: 2696051
I would use a template to wrap both the new and the clear.

template <typename T> inline T* newclear(int n) {
  T* p = new T[n];
  return p;

Author Comment

ID: 2696100
It seems that no one understood my question.

I KNOW what to do and how to do to make my program work at run-time .

But , instead of keeping searching and replacing all clear() with cleard() , i hope that the compiler finds them with me .

nietod : why cleard should do ZeroMemory(*sizeof(*y) , since cleard already knows the size of the array ?

The problem is in clear() . The pointer passed to clear should be a static array . If it is a dynamic one , sizeof() returns 4 . Would size of *x return the correct value in both cases that the array passed is static or dynamic ?

LVL 10

Accepted Solution

RONSLOW earned 30 total points
ID: 2696134
well .. if you want to have the compiler find all the clears for you, just remove the definition. Although a text editor would be better :-)

What you want is COMPILE time assertions.  You can do these with templates.

template <bool> struct tassert { typedef int assertion; };
template <> struct tassert<false> {};

#define CASSERT(X) typedef typename tassert<X>::assertion failed;

Now you can say

#define clear(X) { CASSERT(sizeof(X)>4); ZeroMemory(X,sizeof(X); }

This will fail at compile time (ie you'll get an error) if the sizeof X is 4 (ie it is a pointer and not an array variables.

LVL 10

Expert Comment

ID: 2696146
NOTE: there are other ways to get compiler time assert (using templates) eg.

template <bool b> class assert;
class assert<true>{};
#define CASSERT(X) assert<X>();


bascially, by using a template with a bool param, you get either something valid or invalid.  Other examples include the template param giving array dim (-ve is an error).
LVL 22

Expert Comment

ID: 2696233
>>  i hope that the compiler
>> finds them with me
that is not the compiler's job.  That is a good job for a text editor.

>>  why cleard should do ZeroMemory(*sizeof(*y) ,
>> since cleard already knows the size of
>> the array ?
How does it know that?  I was assuming that x is the number of entries and  y is a pointer to the array.  How does it know the size of the array?

>> The problem is in clear() . The pointer passed to
>> clear should be a static array
If clear() is written to assume that it is passed a pointer to a static array, and it sounds like you have, then you can't expect it to work with a dynamic array.  You must take a different approach with a dynamic array.  You will have to supply the number of entries in the array and some means for it to find the size of an entry (like sizeof(*y)).

>> Would size of *x return the correct value
sizeof() always returns the correct valyue, that just might not be the value you want.  If "x" is a pointer to an array, then sizeof(*x) will return the size of a single item in the array.  You can multiple this byt he number of items in the array to get the size of the array.  That is what my code was doing.

Expert Comment

ID: 2696239
you can use nietod comment
it one of the options for the GetSize func

to make the GetSize i should know how your array is build how can i find it's length <like in array of char i use strlen>
LVL 10

Expert Comment

ID: 2698688
I can see what WxW wants here ... if sometimes he wants to use 'clear' other times 'cleard'.

He, quite legitimately, wants the compiler to tell him when he does the wrong thing.

This is a VERY sensible thing to want.

You should be able to write you code so that the compiler tells you if you do something stupid.  It is good programming paractice to do so.  Examples of this are:

Using const everywhere where it is applicable so you avoid calling functions that can modify a value that should be constant.

Using the convention:
  if (0 == value)
instead of
  if (value == 0)
so that the compiler will generate an error if you mistakenly us '=' instead of '=='.

Using #if and #error to do simple compile time assertions (eg. checking that some #defines are compatible, or the size of a variable is as expected).  Using #error is a bit limited though - hence the templated compile time assertions in my answer

Of course, one can do RUNTIME checking with ASSERT macros etc.  But this relies on having test cases in place that exercises every line of code with all possible conditions.  Such testing is a wonderful thing to have, but one's code shouldn't rely on that.

Having the compiler pick up errors for you at compiler time is always the best option.  And a request for this by WxW should be commended as common sense.

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now