Wednesday, February 24, 2010

multi-statement macros - A Coding practise

This is an interesting topic about Macro Usage

I have a macro

#define SWAP(X,Y) { X = X+ Y; Y = X - Y; X = X - Y; }

So, The above macro swaps two numbers.

I can use

int x = 5, y =4;
SWAP(x,y);

Works perfect.

Now I will use the same as

if ( x > 0)
SWAP(X,Y);

The above one also works fine.

Now
if ( x > 0)
SWAP (x,y);
else
printf("\n X is Below Zero");

So..will the above works.

Noooo..
Before getting solution let us understand the problem my expanding:

if (x > 0)
{
x =x + y;
y = x - y;
x = x -y;
};
else
printf("\n X is Below Zero");

If we compile the above we will get the error like "
 "ERROR!!! "parse error before else"
Because of the extra semi-colon before Else.


So, the solution is embed the multi-staement macro between do-while(0) loop :)

So, the macro defination would be

#define SWAP(X,Y) \
do { \
X = X+ Y; \
Y = X - Y; \
X = X - Y; \
}while (0)

Thats it..

This is the safest way of using multi-statemetn macros ..

OR
There is another Simple way which is bruit-forcing a coding standard for coders ...and here is the rule:

Never forget to use parenthesis even the functional block has one statement
that means

instead of using
if (x > 0)
SWAP (x,y);
else
printf("\n X is Below Zero");

we should use :
if (x > 0)
{
SWAP(x,y);
}
else
{
printf("\n X is Below Zero");
}

Sunday, February 21, 2010

Boost Pointers

scoped_ptr for automatic destruction:

Using normal pointersUsing scoped_ptr
Collapse
  void Sample1_Plain() {   CSample * pSample(new CSample);    if (!pSample->Query() )   // just some function...    {     delete pSample;     return;   }    pSample->Use();   delete pSample;  }
Collapse
#include "boost/smart_ptr.h"   void Sample1_ScopedPtr() {   boost::scoped_ptr<CSample>               samplePtr(new CSample);    if (!samplePtr->Query() )   // just some function...      return;           samplePtr->Use();  }



==========================================================================


Reference counting pointers(shatrd_ptr) track how many pointers are referring to an object, and when the last pointer to an object is destroyed, it deletes the object itself, too.

The boost::shared_ptr implementation has some important features that make it stand out from other implementations:

  • shared_ptr<T> works with an incomplete type:

    When declaring or using a shared_ptr<T>, T may be an "incomplete type". E.g., you do only a forward declaration using class T;. But do not yet define how Treally looks like. Only where you dereference the pointer, the compiler needs to know "everything".

  • shared_ptr<T> works with any type:

    There are virtually no requirements towards T (such as deriving from a base class).

  • shared_ptr<T> supports a custom deleter

    So you can store objects that need a different cleanup than delete p. For more information, see the boost documentation.

  • Implicit conversion:

    If a type U * can be implicitly converted to T * (e.g., because T is base class of U), a shared_ptr<U> can also be converted to shared_ptr<T> implicitly.

  • shared_ptr is thread safe

    (This is a design choice rather than an advantage, however, it is a necessity in multithreaded programs, and the overhead is low.)


    Using shared_ptr in containers

    Many container classes, including the STL containers, require copy operations (e.g., when inserting an existing element into a list, vector, or container). However, when this copy operations are expensive (or are even unavailable), the typical solution is to use a container of pointers:

    Collapse
    std::vector<CMyLargeClass *> vec; vec.push_back( new CMyLargeClass("bigString") );

    However, this throws the task of memory management back to the caller. We can, however, use a shared_ptr:

    Collapse
    typedef boost::shared_ptr<CMyLargeClass>  CMyLargeClassPtr; std::vector<CMyLargeClassPtr> vec; vec.push_back( CMyLargeClassPtr(new CMyLargeClass("bigString")) );

    Very similar, but now, the elements get destroyed automatically when the vector is destroyed - unless, of course, there's another smart pointer still holding a reference.

    Rules : shared_ptr usage

    • When creating a smart pointer, you explicitly have to write ..._ptr<T> myPtr(new T)
    • You cannot assign a T * to a smart pointer
    • You cannot even write ptr=NULL. Use ptr.reset() for that.
    • To retrieve the raw pointer, use ptr.get(). Of course, you must not delete this pointer, or use it after the smart pointer it comes from is destroyed, reset or reassigned. Use get() only when you have to pass the pointer to a function that expects a raw pointer.
    • You cannot pass a T * to a function that expects a _ptr<T> directly. You have to construct a smart pointer explicitly, which also makes it clear that you transfer ownership of the raw pointer to the smart pointer. (See also Rule 3.)
    • There is no generic way to find the smart pointer that "holds" a given raw pointer. However, the boost: smart pointer programming techniques illustrate solutions for many common cases.
    • No circular references - If you have two objects referencing each other through a reference counting pointer, they are never deleted. boost provides weak_ptrto break such cycles (see below).


=============================

Saturday, February 13, 2010

find and replace in a set of files using VIM

In Vim, when we need to replace text in a file, we use the substitute command.
:s/old_text/new_text/

This will replace the first occurrence of "old_text" with "new_text" for the current cursor line.

==

:%s/old_text/new_text/g

To substitute all matching occurrences in the line, add the flag 'g' which refers to global
To substitute all the file occurrences of the pattern, add the '%' before the substitute command.

====
Vim alerts if it didn't find the pattern, vim throws alert for not finding the same. So, to disable that error
add "e" with "g" option

:%s/old_text/new_text/ge
====

To apply Vim command to all the templates files, I will use the 'args' command.
will pass all the templates files in the app/views folder to 'args' using wildcards.

:args /home/venkat/files/*
to do two level directories inclusion for args
:args /home/venkat/files/*/*
====

After we passed the required files to 'args' , we can use this variable for whatever purpose we would like by using the command 'argdo'.


:argdo %s/venkat/nivvy/g | update

UPDATE MAKES THE FILES TO WRITE IF FILES ARE MODIFIED.

If the searched string is not present vim throws error and the global replacement will stop. So, to mask the error "e" option will help by tying with "g" as below

:argdo %s/venkat/nivvy/ge | update

To get confirmation for each replacement

:argdo %s/venkat/nivvy/gec | update

===

Over all

ex: to replace venkat with nivvy in set of files in a directory /home/venkat/files

:args /home/venkat/files/*
:argsdo %s/venkat/nivvy/gce | update

Interesting right :)

Thursday, February 11, 2010

A Coding Practise for Structure Assignment

Today I found one interesting thing :
This is in general can be a part of coding guidelines if we dont have.
NEVER USING = OPERATOR TO ASSIGN THE STRUCTURES. WE SHOULD RECOMMEND TO USE MEMCPY INSTEAD.
ex:
struct {
int rollNum;
name char[255];
} s1, s2;

Here lets suppose if we want to copy the data from s2 to s1 variable.
we can allways do
s1 = s2;
which is correct also.

But let us take an hypothetical scenario wherein we want to make this student structure into a member variable for another structure like
struct ScoreCard {
struct student s;
};
struct ScoreCard *pScoreCard;
pScoreCard = (struct ScoreCard *)malloc(sizeof(struct ScoreCard));
then (s1 = s2 ) kind of code breaks if we do as
pScoreCard->s = s2;

reason being pScoreCard is heap memory and it leads to SEGV.

Let us suppose coder wrote as (as per the new guideline)
memcpy(&s1, sizeof(struct student), &s2);
then there is mere change the the above one by prefixing the pointer

memcpy(pScoreCard->s1, sizeof(struct student), &s2).


Thats it.