Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 397
  • Last Modified:

Definition of macros

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 .
0
WxW
Asked:
WxW
  • 4
  • 4
  • 3
  • +1
1 Solution
 
nietodCommented:
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.
0
 
WxWAuthor Commented:
The array is not a STL array

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

I talk only for arrays with char[] ( buffers )
0
 
ntdragonCommented:
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(...))
 



0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

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

How can GetSize get the size of the object ?
0
 
nietodCommented:
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.
0
 
nietodCommented:
Opps I got a parenthesis wrong.

#define cleard(x,y) ZeroMemory(x*sizeof(*y))
0
 
RONSLOWCommented:
I would use a template to wrap both the new and the clear.

eg.
template <typename T> inline T* newclear(int n) {
  T* p = new T[n];
  ZeroMemory(p,n*sizeof(T));
  return p;
}
0
 
WxWAuthor Commented:
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 ?


0
 
RONSLOWCommented:
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.

0
 
RONSLOWCommented:
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>();

etc.

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).
0
 
nietodCommented:
>>  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.
0
 
ntdragonCommented:
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>
0
 
RONSLOWCommented:
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.
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.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 4
  • 4
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now