Search

Sponsored Links

Meta

Categories

Archives

Recent Posts

RSS Feeds

31
Oct

Interrupt latency and its causes

Interrupt latency is the total delay experienced by a device from the time it raises an interrupt to the time its interrupt service routine begins to execute.The delay introduced can be any one or all of the following below reasons:

  • Time the processor takes to complete the current instruction,do the necessary chores(e.g flush the instruction pipeline and read the interrupt vector) and jump to the trap handler and interrurpt dispatcher part of the kernal
  • Time kernal takes to disable the external interrupts
  • Time required to complete the immediate ISR of higher priority interrupts if any
  • Time the kernal takes to save the context of the interrupted thread,identify the interrupting device, and get the starting address of ISR

The sum of all the above factors is called Interrupt latency.

Popularity: 4%

31
Oct

C/C++ Questions asked in various job interviews

C
==

-> volatile, static, const, register vars
-> Sections/Segments (text, data, stack, heap, bss, etc) of an ELF file
-> where various variables stored
local, formal vars: stack
  static,global (unintialised): bss (block start by symbol)
  static, global(initialised) : data section
  vars allocated thru malloc, new: heap

-> static linking (.a), dynamic linking and loading (.so)
-> Bitwise operations
-> swap two vars without using tmp var
  a=a+b; b=a-b; b= a-b;
u can also swap with using xor operations
  a^=b^=a^=b? (ofcourse this doesn’t work always as u expected, check the sequence point.. modify it)
-> calling conventions
info: c-calling convention, standard calling convention, pascal. etc. (this stuff specific windows,
  unix don’t bother about this, it just uses c calling convention)

->

C++

===
-> Difference between structure and class
-> access specifiers
-> Whats the size of an empty class
-> When do you use composition/aggregation and inheritance
-> When RTTI useful?
-> inline, macros
-> virtual polymorphism (abt vtables, vptrs also)
-> virtual destructors, why not virtual constructors
-> If u invoke a virtual function in constructor what will happen
-> How static behave in C++
-> Name mangling (all related issues like function overloading, using a C or other language function, etc)
-> oop concepts (just abstraction, encapsulation, inheritance, polymorphism)
-> copy constructors
-> “delete this”… is it advisable to use like this? is it useful in any situation?
-> what happens if an exception occurs in between construction of an object
-> If I link a library which I compiled on solaris with a linux executable, will it work?
  why?
-> difference between #define constants and enums
-> class
  {
   enum x{one, two}X1;
   enum y{one, two}Y1;
  };
  is this is OK?

Popularity: 27%

31
Oct

Questions asked in various job interviews (in Programming)

Programming
===========

-> Write a program to search a list of unsorted elements with only one condition
Ans:
  Normal routine: for(i=0;i Manage an array efficiently to implement two stacks on it
Ans:
  manage like this:

   ————————————
   |1st stack–>  <–2nd stack|

  ————————————-

 no explicit bounds

Write a program to traverse a n-ary tree and store the nodes in disk in such way that
tree is reconstructable from the storage

Ans: like java’s serialise data structures

-> Write a program to traverse an array spirally
Ans: write this using directions and maintaining states

-> Write a program to find sub-array of any number of elements with optimum
sum-value in an array (array elements may be -ve)

-> Reverse a double linked list

-> Reverse a single linked list
Ans: use a stack to reverse it

-> Write a recursive program to print a linked list reversely

print(Node *node)
  {
    if(node->next)
     print(node->next)
   else
    return;
  printf(node->info)
 }

-> How do you find loops in a single linked list
  1) use flags
  2) use two or three pointers and increment them at different levels
      like one ptr with ptr=ptr->next , another with second_ptr=second_ptr->next->next.
  if these pointers meet, then it got loops

-> Write a program to find x^n in O(log n)

 

  xpown(x,n)
  {
    val = x;

    do {
      if(n % 2)
        val *= x;
      else
        val *= val;
    }while(n /= 2);
 }

 

 

-> Write a program for preorder traversal without using recursion
ans: use stack

-> Write a program to traverse a binary tree in level by level manner
ans: its just BFS… use queue

-> finding a number is power of 2 or not
ans:
if(!(n & n-1)) printf(”power of 2″);
better answer like this “count number of 1’s… if(count==1) power of 2)

->In an unsorted array find the sum of 3 maximum numbers in less than O(n) time
ans: 1)do bubble sort until u sort 3 elemnts then stop it, sum the nums
   2) build heap (O(n)), delete_max 3 elements (O(logn))

-> in a sorted array only two elements are misplaced, find the desired element still
  maintaining the o(logn) time

-> basics of all data structres

Popularity: 33%

31
Oct

Convert DOS, UNIX, APPLE Line Feeds and Carriage Returns (CR, LF)

DOS uses Carriage Return (\r), Line Feed (\n) for line termination, where as UNIX uses only Line Feed for line termination, APPLE uses carriage return for same purpose. Here is a program which makes one operating system’s text file compatible with other operating system’s text file by conevrting the line feeds and carriage returns according to the system.

enum {DOS_TO_UNIX, DOS_TO_APPLE, UNIX_APPLE_TO_DOS};
 
int ConvertCRLF(char* file, int mode)
{
  //LF-CRLF Converts anything (Unix or Apple) to the DOS standard CRLF.
  //CRLF-CR Converts DOS text to the Apple standard CR.
  //CRLF-LF Converts DOS text to the Unix standard LF.
 
  FILE *fp = NULL;
  FILE *wfp = NULL;
  int ch = 0;
 
  fp = fopen(file, "rw+");
  if (!fp)
  {
    return -1;
  }
 
  wfp = fopen("temp.file", "rw+");
  if (!fp)
  {
    return -1;
  }
 
  while(!feof(fp))
  {
    ch = fgetc(fp);
    switch(mode)
    {
      case DOS_TO_UNIX:
        chnext = fgetc(fp);
        if ((ch == '\r') && (chnext == '\n'))
        {
          fputc('\n', wfp);
        }
        else
        {
          fputc(ch, wfp);
          fputc(chnext, wfp);
        }
        break;
      case DOS_TO_APPLE:
        chnext = fgetc(fp);
        if ((ch == '\r') && (chnext == '\n'))
        {
          fputc('\r', wfp);
        }
        else
        {
          fputc(ch, wfp);
          fputc(chnext, wfp);
        }
        break;
      case UNIX_APPLE_TO_DOS:
        if ((ch == '\r') || (ch == '\n'))
        {
          fputc('\r', wfp);
          fputc('\n', wfp);
        }
        else
        {
          fputc(ch, wfp);
        }
        break;
     }
  }
  return 0;
}

Popularity: 8%

31
Oct

Binary Compatibility

The Theory of Binary Compatibility

In a software system made up of a number of independently evolving parts–many of which are evolving,, yet will be

built to work with last year’s version of that system–it is of vital importance to be able to predict and control

the effect of changes made to one component on untold numbers of unknown components that may be dependent on it.

When a change can be shown not to break any law-abiding software that worked with the component before the change,than that change is a backward compatible change. When a change is such that all software that functions correctly

within the new system will also work with the old system then that change is said to be forward compatible.Backward compatibility is generally the overriding requirement, with forward compatibility an added bonus.

(Bug fixes, for instance, are by their very nature not forward compatible.) In descending order of difficulty:Binary compatibility is to do with the effects of putting separately built yetinterdependent parts together; ie, compatibility across link unit boundaries. When we consider the effects of

linking independently compiled pieces of code together we’re talking about link compatibility. And finally,

a change is source compatible when the source code of dependent components works unchanged when compiled with

the new component.All such considerations are aspects of configuration management–the discipline concerned with assembling

working parts into working systems.

When shipping, one is engaging in a particularly awkward form of configuration management–one which is

concerned with binary compatibility and can’t even physically put the resulting system together for testing:

that is done by customers in the field.

We have to do our configuration management in the abstract. We need to be confident about our work’s compatibilitywith whole classes of independently created software products. To gain this confidence we need to make reasonableassumptions about the behaviour of such software, and derive rules as to the kind of change it will withstand.

The principal working assumption we’ll make about software produced to work with our components is that it adheres

to reasonable software engineering practice; ie, rogue code fraudulently gaining access to all sorts of private bitswe’ll break with joyful abandon. (Unless it happens to be that best-selling piece of software, of course.) On the

other hand, if ever some facility or piece of information has been–or given the impression of being–a legitimate part of a supported interface, we are honour-bound to maintain it forever.Additional assumptions we’ll be making are to do with the behaviour of the C++ implementation we’re working with.

We’ll assume certain things that aren’t in the C++ spec, but are nonetheless fairly reasonable. (This is effectively

limiting implementations of Symbian OS to C++ compilers for which those assumptions are true.)For instance, whereas C++ doesn’t define the layout of of class members across access specifiers, we will assume that

access specifiers have no effect on layout, and that we can therefore relax a data member’s access restrictions as

long as we don’t change declaration order. Similarly, we’ll assume that the order of declaration of virtual memberfunctions is the only thing that affects their order in the virtual table. We’ll assume pointers and references sharea representation, and, with respect to multiple inheritance, we’ll make the assumption that a pointer to a certain

class’s representation remains unchanged when it is converted to a pointer to the first base class in declaration order. (The first base class comes first in the class’s layout.)Furthermore, we’ll assume that C++’s type-safe linkage of compilation units is not in force across link units;

ie, we’ll be able to make well-considered changes to the name and signature of link unit entrypoints.

(This requires link by ordinal everywhere.)

An interface is a contract a provider of services enters into with a client. Either party can “own” the interface.I’ll use the term client interface if the interface is best thought of as belonging to the service provider.

If the interface is defined by the client of the service I’ll call it a provider interface. Client interfacesare normally monomorphic whereas provider interfaces can be–and generally are–polymorphic.

In C++ terms, the public interface of a class is an example of a client interface, and so is the protected

interface (which defines services the class provides to its subclasses). A class’s virtual interface is aprovider interface. The base class specifies services to be provided by derived classes. In terms of link units–DLLs–a client

interface setup exists when a DLL is being used as a shared library.The DLL’s interface is a table of exported functions, knowledge of the indices and meaning of which is

shared between DLL and clients. A shared library comes complete with an import library, which encapsulates

this shared knowledge. The preservation of this information across versions is a necessary condition for compatibility. To this end we maintain a definitions file (.def) which is the source equivalent of theimport library. Freeze files (.frz) are just DEFs by another name. Most Symbian OS DLLs serve as shared libraries.

DLLs also work well in a provider interface setup, both in monomorphic and polymorphic flavours.Monomorphic provider DLLs are useful to choose a particular service provider at configuration time.

Symbian OS examples are the console library (ECONS.dll) and the various libraries adapting the O/S

to hardware variants. The client links to an import library generated from a well-defined definitions

file, which is published for use by providers. Providers link their implementation DLLs using the interface DEF file.Polymorphic provider DLLs (drivers, in a broad sense) allow the client to choose a service provider at

runtime. Providers once again link using a DEF file published by the interface owner. However,the latter doesn’t use an import library this time, but dynamically loads the chosen provider DLL instead.

It then uses its knowledge of the exported entrypoints to invoke the provider’s services. In this case,

the DEF file is to be treated as true source code since the DLL’s functions are looked up programmatically.?

Binary Compatibility in Practice

There’s a number of things all component owners need to do in order to gain control over their binary

interface. Once entry-level binary compatibility is assured we can talk about the sorts of changes youwill be able to make and how to tweak your interfaces in order to maximizes the options.

2.0 Exports - DEF Files

To maintain BC from one release to the next, (this is whilst making only implementation changes) every DLL

interface involved needs to have its definitions file preserved, for all builds. ie, Debug, Release, Unicode Debug, Unicode Release. At ACME this means archiving the definitions files using the versioncontrol system. The definitions file lists the exports definitions, ie, a description of those functions

that are exported from your DLL.

For both MARM and WINS builds you can specify the frozen DEFs (master) files to build with. The build

process will then generate new DEFs - identical to the specified frozen ones, (unless you’ve addedentry points - see later - “Adding Services”) and this new DEF will be used to link the DLL. You can tell MAKMAKE to build

using the frozen export files by adding the following into you.MMP project files

DEFFILE component.DEF

MAKMAKE will look for these files in the BMARM and BWINS directories by default.This will ensure that the exports from a subsequent command-line build of the component are

compatible with the current version.

(the build process automatically mangles the DEF file name so the correct one is used, ie.

componentD.def for a Narrow Debug build, componentUD.def for a Unicode Debug build.) (note that some components do not yet conform to this standard. For MARM builds, somecomponents rename the DEFs to be FRZs - that is a freeze file - but these components are,

over time, being converted to the new build system as described here).?

2.1 MARM Exports file

So where do the .DEF files come from in the first place then ? For MARM, well the MARM build process will always generate a new DEF exportsfile which it leaves lying around in the intermediate build directory. This is a

link-by-ordinal DEF file, so all you have to do is create a BMARM project directory and copy the DEF files here, adding the correct suffix

for the variant.eg, copy…

\epoc32\build\comp\marmd\rel\dll.def –> \project\bmarm\dll..def

\epoc32\build\comp\marmd\deb\dll.def –> \project\bmarm\dllD.def

\epoc32\build\comp\marmd\urel\dll.def –> \project\bmarm\dllU.def

\epoc32\build\comp\marmd\udeb\dll.def –> \project\bmarm\dllUD.def

2.2 WINS Exports file

With WINS, things are a little more complicated. The basic idea is the same and involves

archiving the DEF exports file. First you use a tool called DEFMAKE to generate the initial

DEF files (into a BWINS project directory), as follows…

defmake \epoc32\release\wins\rel\dll.dll \project\bwins\dll.def

defmake \epoc32\release\wins\deb\dll.dll \project\bwins\dllD.def

defmake \epoc32\release\wins\urel\dll.dll \project\bwins\dllU.def

defmake \epoc32\release\wins\udeb\dll.dll \project\bwins\dllUD.def

…DEFMAKE reads the Win32 PE file (the WINS binary you have built), extracting names and

ordinals and produces a link-by-ordinal DEF file, which from now on you will use to link

the DLL. Once you have rebuilt your DLL using this new link-by-ordinal DEF file, the resulting PE file will no longer contain names for DEFMAKE to extract. Luckily you will be archiving theexports file (won’t you ?) and you wont normally need to regenerate them, except when you’re

adding services. (see later - “Adding Services”)

3.0 Adding Services

In general, it is possible to add exported services to your published interface. There arerestrictions on the type of services that may be added. See below (”Allowed Changes”) for a description of these. For both MARM and WINS builds,

this is pretty straightforward. All new services get added atthe end of the automatically generated DEF file, following a build of the component. Simply

replacing the original DEF file with this new one will give these new entry points permanentstatus. (The reason a DEF file is specified in the .MMP file is that this is used as a template when the build process generates the

new one. All matching exports maintain the same ordinal, and all new exports are appended to the new DEF file).4.0 Allowed Changes

Now that we have the mechanism in place, let’s look at some of the changes you can or can’t make to

an interface while preserving backward binary compatibility. Naturally, these remarks only apply to constructs which are part of an external interface. You are free to arrange you internal interfaces as you see fit.Add services to a shared library.

Adding classes, global functions, static member functions and non-virtual member functions is fairly straightforward. Remember to avoid name collisions (as always) and to freeze the

new entry points as soon as the new version of the library is released.You can’t generally add or delete virtual member functions, or even change their order of declaration.

You can’t even override an existing virtual function that was previously inherited. (Existing derived

classes would be left inheriting the wrong function).

All changes to private non-virtual (static and non-static) member functions are OK as long as they arenot accessed through public or protected inline functions; either directly or indirectly.Some friends or member functions affected by the change may be in a different link-unit, in which

case you must make sure that the relevant binaries are kept in synch at all times. If this is notpractical then the change must be disallowed.

You can make changes to private data members that are not accessed through any public or protected

inline functions - directly or indirectly - provided that the size of the class remains unchangedand that the offset of all public or protected data members or private members accessible through

public or protected inline functions, directly or indirectly, stay the same. If friends or membersof the class exist in a different link unit then all relevant binaries must be kept in synch.You can relax access specifiers; ie, a

protected member can become public, a private member publicor protected. The reverse is not allowed because it would make it impossible to draw any conclusionsfrom a member’s current access specification. An exception to this rule can be made if a forwarding

inline function is left in its place.Similarly, you can bestow friendship upon additional classes or functions, but, once given it can’t

be withdrawn. Friendship is forever.

You can change the size of a class provided it has only private, non-inline constructors and eithera virtual destructor or if it has a non-virtual destructor it mustn’t declare or inherit an operator

delete() of the form with two arguments. In this case only friends and members can allocate memory

for and construct instances of the class. The operator delete() requirement in the presence of anon-virtual destructor exists because in that case the compiler will supply the second argument - the size of the object - to the

delete operator based on the version of the class declaration ithas seen. Further restrictions are as for changes to private data members. Note that a class without constructors gets a compiler-generated,

public default constructor and a class withouta copy constructor gets a public default copy constructor. (Constructor generation, however, can be inhibited higher up in the

class hierarchy, as is the case for copy constructors in classesderived from CBase.)

You can widen the range of valid inputs to a function, or narrow the range of possible outputs.

You can’t change the interpretation of an existing valid input or change the meaning of an

existing output value. An enumeration can be added to but not reordered, say.

You can change the name and/or signature of a function if the change preserves or changesthe input or output ranges along acceptable lines. A non-const parameter can be made const, a reference to a

class can be changed to a reference to first base class, etc.As a single, unlikely exception, you can add a virtual function to a class or implement a previously inherited

virtual function that wasn’t public if classes derived from theprevious incarnation of the class wouldn’t have been able to be instantiated; ie, if the

class had only private constructors or had a private destructor. (Yeah, right.)I guess there’s a general flavour to these rules, which can be used to derive some guidelines

for defensive interface definition. It goes something like: A change is OK if eitherYou can pin down and fix every single line of code affected by it, and make sure that the

fixed code goes everywhere the change goes. This only works if no aspect of the change escapes from the

private domain.The change is demonstrably compatible with all possible clients, not just current ones or

ones you are aware of.

Unless you are confident that an interface will never need changing (this is a valid attitude,especially if you turn out to be right), you should be defensive about what leaks out of your interfaces. No information should escape

for no particular reason.Quite often information seems to make it out into the public domain by “accident”. Panic numbers,message numbers, purely private definitions such as hard-coded directory names, and indeed entire

private headers are but a few examples. Scores of private libraries have their import librariesreleased. Avoid doing this if at all possible. What you do not publish you do not have to freeze. Perhaps the most common violation of

this principle is overuse of the protected keyword. Protectedis often just slapped on by default, on the grounds that it allows more flexibility. The reverse is

true. Unnecessary protected interfaces have to be supported in perpetuity just as legitimateones have to be. Protected belongs only in classes designed as base classes in a framework.

Perhaps another thing that is apparent from the above is that the options with virtual functionsare severely limited. In frameworks with high fluidity it may therefore be appropriate to add in

one or two “spare” virtual functions. A restricted class of changes may be supported by pressingsuch a spare into service. If a framework suddenly, courtesy of a new category of concrete classes, acquires

new attributes along a new “dimension”. As a contrived example, should controls all of asudden require a degree of transparency, so that they can be layered with lower layers filtering

through, then a spare virtual function could be given a default behaviour that suits existing (ie, opaque) controls and new, transparent controls can be introduced. This is certainly nopanacea but may be useful in some cases.

?

?

Popularity: 4%

27
Oct

Reference Counting

//============================================================================

// Contents:

//

// Definition of ReferenceCounter abstract base class that confers reference

// counting features for derived classes. Global functions are provided that

// make any class derived from ReferenceCounter satisfy the ReferenceCounter

// requirements defined for any parameter of countable_ptr.

//

//

//============================================================================

#ifndef _REFERENCECOUNTER_H_

#define _REFERENCECOUNTER_H_

#include // for size_t

// Description:

//

// Definition of ReferenceCounter abstract base class, which provides a mechanism

// for reference counting for use by derived classes.

//

// Notes:

//

// The ReferenceCounter class is intended to be used as a mix-in, but without

// any polymorphic behaviour; its principle aim is to provide implementation

// for derived classes (ie a mix-imp). As such, there are no virtual

// functions. Making the constructor protected has the effect of making the

// class abstract, and making the destructor ensures that unsafe destruction

// via a counability * is not possible.

//

// Copying is not considered meaningful for such a class, and so copying

// semantics have been disabled. This does mean that derived classes are

// required to define their own copying semantics if that is what is

// required, but this is expected of any good citizen class and so is not

// considered an unreasnable imposition.

//

// ReferenceCounter is not seen as a concrete property of derived classes, and

// therefore is not part of an object’s logical state. This means that all

// the operations in ReferenceCounter are const, and the count member is mutable.

// If your compiler does not support mutable you can remove it and modify the

// implementation to use const_cast where appropriate.

//

// Related member functions (method categories) are placed under their own

// commented access specifiers.

//—————————————————————————-

class ReferenceCounter{

public: // manipulation

void acquire() const;void release() const;size_t acquired() const;

protected: // construction and destruction

ReferenceCounter();

~ReferenceCounter();

private: // representation

mutable size_t count;ReferenceCounter(const ReferenceCounter &);ReferenceCounter &

operator=(const ReferenceCounter &);};

//—————————————————————————-

// Description:

//

// Declaration of global functions that allow classes derived from

// ReferenceCounter to satisfy countable requirements.

//

//—————————————————————————-

void acquire(const ReferenceCounter *);

void release(const ReferenceCounter *);size_t acquired(const ReferenceCounter *);

#endif

?

//============================================================================

// Contents:

//

// Definition of ReferenceCounter class member and global functions.

//

// History:

//

// Initial version created by Kevlin Henney, kevlin@acm.org, January 1998.

//

// Permissions:

//

// Copyright Kevlin Henney, 1998. All rights reserved.

//

// Permission to use, copy, modify, and distribute this software for any

// purpose is hereby granted without fee, provided that this copyright and

// permissions notice appear in all copies and derivatives, and that no

// charge may be made for the software and its documentation except to cover

// cost of distribution.

//

// This software is provided “as is” without express or implied warranty.

//

// Notes:

//

// All the functions defined are likely candidates for explicit inlining, but

// for the purposes of demonstration such an optimisation has not been deemed

// necessary.

//

// This code has been written to conform to standard C++ (in final draft

// status at the time of writing). It has been compiled successfully using

// the operational subset of standard features implemented by Microsoft

// Visual C++ 5.0.

//============================================================================

#include “ReferenceCounter.hpp”

//—————————————————————————-

// Description:

//

// Definition of ReferenceCounter class member functions.

//

// Notes:

//

// The implementation presented is not guaranteed to count safely across

// threads. Threadsafe counting can be implemented either by modifying the

// code below (eg under Win32 using InterlockedIncrement instead of ++), or

// by providing an additional class (eg threadsafe_ReferenceCounter). Note that

// in the case of modifying code in this file, not having inline functions

// supports a binary compatible change, ie the decision as to whether or not

// to use a threadsafe version can be deferred to link time.

//—————————————————————————-

void ReferenceCounter::acquire() const

{

++count;

}

void ReferenceCounter::release() const

{

–count;

}

size_t ReferenceCounter::acquired() const

{

return count;}

ReferenceCounter::ReferenceCounter()

: count(0)

{

}

ReferenceCounter::~ReferenceCounter()

{

}

//—————————————————————————-

// Description:

//

// Definition of ReferenceCounter global non-template functions.

//—————————————————————————-

void acquire(const ReferenceCounter *ptr){

if(ptr){

ptr->acquire();

}

}

void release(const ReferenceCounter *ptr){

if(ptr){

ptr->release();

}

}

size_t acquired(const ReferenceCounter *ptr){

return ptr ? ptr->acquired() : 0;}

Popularity: 3%

27
Oct

When to use pointer, when to use reference?

Use references when you can, and pointers when you have to. References are usually preferred over pointers whenever you don’t need “reseating”. This usually means that references are most useful in a class’s public interface.

References typically appear on the skin of an object, and pointers on the inside. The exception to the above is where a function’s parameter or return value needs a “sentinel” reference. This is usually best done by returning/taking a pointer, and giving the NULL pointer this special significance (references should always alias objects, not a dereferenced NULL pointer).

Note: Old line C programmers sometimes don’t like references since they provide reference semantics that isn’t explicit in the caller’s code. After some C++ experience, however, one quickly realizes this is a form of information hiding, which is an asset rather than a liability. E.g., programmers should write code in the language of the problem rather than the language of the machine

Popularity: 11%

27
Oct

Optimizing C and C++ Code

Embedded software often runs on processors with limited computation power, thus optimizing the code becomes a necessity. In this article we will explore the following optimization techniques for C and C++ code developed for Real-time and Embedded Systems.

  1. Adjust structure sizes to power of two
  2. Place case labels in narrow range
  3. Place frequent case labels first
  4. Break big switch statements into nested switches
  5. Minimize local variables
  6. Declare local variables in the inner most scope
  7. Reduce the number of parameters
  8. Use references for parameter passing and return value for types bigger than 4 bytes
  9. Don’t define a return value if not used
  10. Consider locality of reference for code and data
  11. Prefer int over char and short
  12. Define lightweight constructors
  13. Prefer initialization over assignment
  14. Use constructor initialization lists
  15. Do not declare “just in case” virtual functions
  16. In-line 1 to 3 line functions

Adjust structure sizes to power of two

When arrays of structures are involved, the compiler performs a multiply by the structure size to perform the array indexing. If the structure size is a power of 2, an expensive multiply operation will be replaced by an inexpensive shift operation. Thus keeping structure sizes aligned to a power of 2 will improve performance in array indexing.

Place case labels in narrow range

If the case labels are in a narrow range, the compiler does not generate a if-else-if cascade for the switch statement. Instead, it generates a jump table of case labels along with manipulating the value of the switch to index the table. This code generated is faster than if-else-if cascade code that is generated in cases where the case labels are far apart. Also, performance of a jump table based switch statement is independent of the number of case entries in switch statement.

Place frequent case labels first

If the case labels are placed far apart, the compiler will generate if-else-if cascaded code with comparing for each case label and jumping to the action for leg on hitting a label match. By placing the frequent case labels first, you can reduce the number of comparisons that will be performed for frequently occurring scenarios. Typically this means that cases corresponding to the success of an operation should be placed before cases of failure handling.

Break big switch statements into nested switches

The previous technique does not work for some compilers as they do not generate the cascade of if-else-if in the order specified in the switch statement. In such cases nested switch statements can be used to get the same effect.
To reduce the number of comparisons being performed, judiciously break big switch statements into nested switches. Put frequently occurring case labels into one switch and keep the rest of case labels into another switch which is the default leg of the first switch.
Splitting a Switch Statement

//This switch statement performs a switch on frequent 
//messages and handles the infrequent messages 
//with another switch statement in the default 
//leg of the outer 
// switch statement 
pMsg = ReceiveMessage();
switch (pMsg->type)
{ 
  case FREQUENT_MSG1: 
    handleFrequentMsg1();
    break;
  case FREQUENT_MSG2:
    handleFrequentMsg2();
    break;
  . . .
  case FREQUENT_MSGn:
    handleFrequentMsgn();
    break;
  default:
    // Nested switch statement for 
    //handling infrequent messages. 
    switch (pMsg->type)
    {
      case INFREQUENT_MSG1:
        handleInfrequentMsg1();
        break;
      case INFREQUENT_MSG2:
        handleInfrequentMsg2();
        break;
       . . .
      case INFREQUENT_MSGm:
        handleInfrequentMsgm();
        break;
    }
}

Minimize local variables

If the number of local variables in a function is less, the compiler will be able to fit them into registers. Hence, it will be avoiding frame pointer operations on local variables that are kept on stack. This can result in considerable improvement due to two reasons:

All local variables are in registers so this improves performance over accessing them from memory.
? If no local variables need to be saved on the stack, the compiler will not incur the overhead of setting up and restoring the frame pointer.

Declare local variables in the inner most scope

Do not declare all the local variables in the outermost function scope. You will get better performance if local variables are declared in the inner most scope. Consider the example below; here object a is needed only in the error case, so it should be invoked only inside the error check. If this parameter was declared in the outermost scope, all function calls would have incurred the overhead of object a’s creation (i.e. invoking the default constructor for a).
Local varialble scope

int foo(char *pName)
{
  if (pName == NULL)
  {
    A a;
    ...
    return ERROR;
  }
  ...
  return SUCCESS;
}

Reduce the number of parameters

Function calls with large number of parameters may be expensive due to large number of parameter pushes on stack on each call. For the same reason, avoid passing complete structures as parameters. Use pointers and references in such cases.

Use references for parameter passing and return value for types bigger than 4 bytes

Passing parameters by value results in the complete parameter being copied on to the stack. This is fine for regular types like integer, pointer etc. These types are generally restricted to four bytes. When passing bigger types, the cost of copying the object on the stack can be prohibitive. In case of classes there will be an additional overhead of invoking the constructor for the temporary copy that is created on the stack. When the function exits the destructor will also be invoked.

Thus it is efficient to pass references as parameters. This way you save on the overhead of a temporary object creation, copying and destruction. This optimization can be performed easily without a major impact to the code by replacing pass by value parameters by const references. (It is important to pass const references so that a bug in the called function does not change the actual value of the parameter.

Passing bigger objects as return values also has the same performance issues. A temporary return object is created in this case too.

Don’t define a return value if not used

The called function does not “know” if the return value is being used. So, it will always pass the return value. This return value passing may be avoided by not defining a return value which is not being used.

Consider locality of reference for code and data

The processor keeps data or code that is referenced in cache so that on its next reference if gets it from cache. These cache references are faster. Hence it is recommended that code and data that are being used together should actually be placed together physically. This is actually enforced into the language in C++. In C++, all the object’s data is in one place and so is code. When coding is C, the declaration order of related code and functions can be arranged so that closely coupled code and data are declared together.

Prefer int over char and short

With C and C++ prefer use of int over char and short. The main reason behind this is that C and C++ perform arithmetic operations and parameter passing at integer level, If you have an integer value that can fit in a byte, you should still consider using an int to hold the number. If you use a char, the compiler will first convert the values into integer, perform the operations and then convert back the result to char.

Lets consider the following code which presents two functions that perform the same operation with char and int.
Compaing char and int operations

char sum_char(char a, char b)
{
  char c;
  c = a + b;
  return c;
}
 
int sum_int(int a, int b)
{
  int c;
  c = a + b;
  return c;
}

A call to sum_char involves the following operations:

  1. Convert the second parameter into an int by sign extension (C and C++ push parameters in reverse)
  2. Push the sign extended parameter on the stack as b.
  3. Convert the first parameter into an int by sign extension.
  4. Push the sign extended parameter on to the stack as a.
  5. The called function adds a and b
  6. The result is cast to a char.
  7. The result is stored in char c.
  8. c is again sign extended
  9. Sign extended c is copied into the return value register and function returns to caller.
  10. The caller now converts again from int to char.
  11. The result is stored.

A call to sum_int involves the following operations:

  1. Push int b on stack
  2. Push int a on stack
  3. Called function adds a and b
  4. Result is stored in int c
  5. c is copied into the return value register and function returns to caller.
  6. The called function stores the returned value.

Thus we can conclude that int should be used for all interger variables unless storage requirements force us to use a char or short. When char and short have to be used, consider the impact of byte alignment and ordering to see if you would really save space. (Many processors align structure elements at 16 byte boundaries)?

Define lightweight constructors

As far as possible, keep the constructor light weight. The constructor will be invoked for every object creation. Keep in mind that many times the compiler might be creating temporary object over and above the explicit object creations in your program. Thus optimizing the constructor might give you a big boost in performance. If you have an array of objects, the default constructor for the object should be optimized first as the constructor gets invoked for every object in the array.

Prefer initialization over assignment

Consider the following example of a complex number::

Initialization and assignment

void foo()
{
  Complex c;
  c = (Complex)5;
}
 
void foo_optimized()
{
  Complex c = 5;
}

In the function foo, the complex number c is being initialized first by the instantiation and then by the assignment. In foo_optimized, c is being initialized directly to the final value, thus saving a call to the default constructor of Complex.

Use constructor initialization lists

Use constructor initialization lists to initialize the embedded variables to the final initialization values. Assignments within the constructor body will result in lower performance as the default constructor for the embedded objects would have been invoked anyway. Using constructor initialization lists will directly result in invoking the right constructor, thus saving the overhead of default constructor invocation.? br /> In the example given below, the optimized version of the Employee constructor saves the default constructor calls for m_name and m_designation strings.
Constructor initialization lists

Employee::Employee(String name, String designation)
{
  m_name = name;
  m_designation = designation;
}
/* === Optimized Version === */
Employee::Employee(String name, String designation): m_name(name), m_destignation (designation)
{
}

Do not declare “just in case” virtual functions

Virtual function calls are more expensive than regular function calls so do not make functions virtual “just in case” somebody needs to override the default behavior. If the need arises, the developer can just as well edit the additional base class header file to change the declaration to virtual.

In-line 1 to 3 line functions

Converting small functions (1 to 3 lines) into in-line will give you big improvements in throughput. In-lining will remove the overhead of a function call and associated parameter passing. But using this technique for bigger functions can have negative impact on performance due to the associated code bloat. Also keep in mind that making a method inline should not increase the dependencies by requiring a explicit header file inclusion when you could have managed by just using a forward reference in the non-inline version.

Popularity: 21%

25
Oct

Reverse linked list using pointers

Reversing a single list can achieved using a stack very easily. however this can be done without using stack, and by simply using three additional pointers. Let us say we are using curr, next, result pointers, curr points to current node, next obviously points to the next node, result points to the new reversed linked list.
here is the pictorial representation of this operation for better understanding…
SLL_reverse_1
now result holds one reversed node, and curr points to the rest of the linked list..
SLL_reverse_2

now result holds a pointer to the reversed linked list (reversed two pointers already)…. curr holds rest of the list
SLL_reverse_3

we reversed successfully….
SLL_reverse_4

here is the routine for doing this…..

void reverse_single_linked_list(struct node** headRef)
{
  struct node* result = NULL;
  struct node* current = *headRef;
  struct node* next;
  while (current != NULL)
  {
    next = current->next; // tricky: note the next node
    current->next = result; // move the node onto the result
    result = current;
    current = next;
  }
  *headRef = result;
}

please let me know your comments….

Popularity: 95%

25
Oct

Binary decimal conversion….

Here is a program to convert a binary string to decimal number.
ex. "0101" to 05

Parameters:
binary: is binary string
size: is size of the binary string buffer

int bin2dec(unsigned char *binary, int size)
{
  int i, result = 0;
 
  for(i = 0; i < size; i ++)
  {
    result += (binary[i] - '0') << (size - i - 1);
  }
 
  return result;
}

any comments welcome…

Popularity: 16%

Next Page »