Search

Sponsored Links

Meta

Categories

Archives

Recent Posts

RSS Feeds

22
Jan

Stdarg: Variable Arguments

ANSI C provides macros to support for accessing variable arguments of a function. These macros are va_start, va_arg, va_end.

Which include file to use:
stdarg.h

APIs:
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);

Here is the man page of stdarg

How to declare a variable arguments function:
int varargsfunction(int numargs, …);
“…” three dots at the end signifies variable arguments.

How to call variable argument functions:
here are some examples..

varargsfunction(3, “aa”, “bb”, “cc”);

varargsfunction(”%s%d%s”, “aa”, 22, “cc”);

varargsfunction(”aa”, “bb”, “cc”, NULL);

How to recognize number of arguments, variable types in function while accessing them:
For accessing and processing variables we require basically
          How many arguments passed
          Types of arguments

Here are the methods to identify number of arguments and type of arguments
1)if you know the variable types you are passing then mentioning number of arguments while calling variable argument function would be sufficient. Consider an example where you are passing a string then all integers

int stdargs_function(int numargs, ...)
{
  char *msg;
  int x;
  va_list ap;
 
  va_start(ap, numargs);
  msg = va_arg(ap, char *);
  for (I = 0; i<numargs-1; i++)
  {
    x = va_arg(ap, int);
  }
  va_end(ap);
  return 0;
}

You can call this function as something like
   stdargs_function(4, “ccc”, 23,43,45);

2)if you know the types of variables you are passing then to identify number of arguments passing, terminate the argument list with NULL.

int stdargs_function(int msg, ...)
{
  char *msg;
  va_list ap;
 
  va_start(ap, numargs);
  for (; msg != NULL;)
  {
    msg = va_arg(ap, char *);
  }
  va_end(ap);
  return 0;
}

You can call this function as something like
stdargs_function(”ccc”, “dd”, NULL);

3)make available number of arguments and type arguments available in first argument (ex. printf function)

int stdargs_function(int format_string, ...)
{
  char *msg;
  va_list ap;
 
  numargs = GetNumArgs(format_string);
  va_start(ap, format_string);
  for (i=0;i<numargs; i++)
  {
    type = GetNextFormatSpecifier(format_string);
    switch(type)
    {
      case 'd':
        msg = va_arg(ap, char *);
        break;
      case 's':
        msg = va_arg(ap, int);
        break;
    }
  }
  va_end(ap);
}

You can call this function as something like
stdargs_function(”%d%s”, 23, “dd”);

Is there any other implementation other than stdarg.h:
Yes, varargs.h was used before ANSI C. varargs.h is obsolete now. Varargs usage is slightly different
Than stdargs usage. Stdargs require at least one argument need to be mentioned before using variable args, varargs doesn’t mandate this.

An Example Program:

#include <stdio.h>
#include <stdarg.h>
 
int print(int max, ...);
int main(void)
{
  print(2, "OpenAsthra", "formula pattern");
  print(1, "we are done with this program");
  return 0;
}
 
int print(int numargs, ...)
{
  va_list ap;
  int args = 0;
  char *strings[10];
 
  va_start(ap, numargs);
 
  while(args < numargs)
  {
    strings[args] = va_arg(arg_ptr, char *);
    printf("%s\n";, strings[args++]);
  }
  va_end(ap);
}

 

Popularity: 10%

18
Jan

Binary Streams Utility Classes

Binary streams are commonly used in many applications. They require special care while dealing with them. Here is a binary class which can be deployed and customized according to your need. This binary class has awareness of endian. It act according to endain. If your machine is little endian and you wish to process your binary stream in little endian, then set the mode to little endian. If your machine big endian set the mode to big endian. However little more intelligence yet to be incorporated in case of your machine is little endian and you want the binary stream processing in big endian, in this case you need to use utilities mentioned in the post Little and big endianess explained - part2

There are three classes, BinaryStream, IBinaryStream, OBinaryStream. IBinaryStream is input binary stream and OBinaryStream is output binary stream. You can directly create class instances and attach a buffer and work on it. However you can extend this class by defining some overloading operators to the operations in the class or you can add more functionality to these classes.

#define NUM_BITS_IN_BYTE 8

 

//these classes doesn't bother about whether integers are word aligned or not,
//internally take care of it

//binary stream class
class BinaryStream
{
public:
  BinaryStream()
  {
    buf = NULL;
    len = 0;
    currptr = 0;
    err = STREAM_OK;
    endianness = LITTLE_ENDIAN;
  }

  virtual ~BinaryStream(){};

  enum
  {
    LITTLE_ENDIAN,
    BIG_ENDIAN,
  };

  enum
  {
   BS_SEEK_SET,
   BS_SEEK_CUR,
   BS_SEEK_END,
  };

  enum
  {
    STREAM_OK,
    STREAM_EOF,
    STREAM_FAIL,
  };

  //is stream ok
  bool IsStreamOk()
  {
    return (err == STREAM_OK);
  }

  //is end of stream
  bool eof()
  {
    return (err == STREAM_EOF);
  }

  //can read/write n bytes from stream
  bool IsSpaceAvailableForOperation(unsigned long bytes)
  {
    return (currptr < (buf+len-bytes));
  }

  //attach a buffer to work on
  void Attach(void * buffer, unsigned long length)
  {
    buf = (unsigned char *)buffer;
    currptr = buf;
    len = length;
    err = STREAM_OK;
  }

  //current position in stream
  unsigned long tell()
  {
    return (currptr - buf);
  }

  //seek to offset in stream
  void seek(int offset, int fromwhere)
  {
    switch(fromwhere)
    {
      case BS_SEEK_SET:
          currptr = buf + offset;
          break;
      case BS_SEEK_CUR:
          currptr += offset;
          break;
      case BS_SEEK_END:
          if (offset < 0)
          {
            currptr += offset;
          }
          break;
      default:
          break;
    }
  }
protected:
  int err;
  unsigned char *buf;
  unsigned long len;
  unsigned char *currptr;
  int endianness; //endianness of stream

};

Here is the input binary stream class. It inherits from above binary class.

//input binary stream
class IBinaryStream : public BinaryStream
{
private:
  public:
 
  IBinaryStream(){};
  ~IBinaryStream(){};
 
  //reads a byte from stream
  unsigned char ReadByte()
  {
    if (IsSpaceAvailableForOperation(sizeof(unsigned char)))
    {
      return(*currptr++);
    }
    err = STREAM_EOF;
    return 0;
  }
 
  unsigned short ReadUnsignedShort()
  {
    unsigned short result = 0;
    unsigned char byte1, byte2;
 
    if (IsSpaceAvailableForOperation(sizeof(unsigned short)))
    {
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = ReadByte();
        byte2 = ReadByte();
      }
      else
      {
        byte2 = ReadByte();
        byte1 = ReadByte();
      }
      currptr += sizeof(unsigned short);
      result = byte1;
      return(( result << NUM_BITS_IN_BYTE) | byte2 );
    } /*IsSpaceAvailableForOperation(sizeof(unsigned short)))*/
    err = STREAM_EOF;
    return 0;
  }
 
  unsigned long ReadUnsignedLong()
  {
    unsigned long result = 0;
    if ( IsSpaceAvailableForOperation(sizeof(unsigned long)))
    {
      unsigned char byte1, byte2, byte3, byte4;
 
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = ReadByte();
        byte2 = ReadByte();
        byte3 = ReadByte();
        byte4 = ReadByte();
      }
      else
      {
        byte4 = ReadByte();
        byte3 = ReadByte();
        byte2 = ReadByte();
        byte1 = ReadByte();
      }
      result = byte1;
      result = (result << NUM_BITS_IN_BYTE) | byte2;
      result = (result << NUM_BITS_IN_BYTE) | byte3;
      result = (result << NUM_BITS_IN_BYTE) | byte4;
      currptr += sizeof(unsigned long);
      return result;
    } /*IsSpaceAvailableForOperation(sizeof(unsigned long)))*/
    err = STREAM_EOF;
    return result;
  }
 
  //Reads 'length' number of bytes from the stream and places them in 'data'.
  int read(unsigned char * data, int size)
  {
    if (data && IsSpaceAvailableForOperation(size) )
    {
      memcpy(data, currptr, size);
      currptr += size;
    }
 
    err = STREAM_FAIL;
    return 0;
  }
};

The below class is output binary class, it also inherits from BinaryStream.

//output binary stream
class OBinaryStream : public BinaryStream
{
public:
  OBinaryStream(){};
  virtual ~OBinaryStream(){};
 
  //write into stream
  int write(const unsigned char * data, int size)
  {
    if (data && IsSpaceAvailableForOperation(size))
    {
      memcpy(currptr, data, size);
      currptr += size;
      return size;
    }
    err = STREAM_FAIL;
    return 0;
  }
 
  //write a byte
  int WriteByte(unsigned char n)
  {
    if ( IsSpaceAvailableForOperation(sizeof(unsigned char)))
    {
      *currptr = n;
      currptr += sizeof(unsigned char);
      return sizeof(unsigned char);
    }
    err = STREAM_EOF;
    return 0;
  }
 
  //write a unsigned short
  int WriteUnsignedShort(unsigned short n)
  {
    unsigned char byte1, byte2;
 
    if ( IsSpaceAvailableForOperation(sizeof(unsigned short)))
    {
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = (unsigned char)n;
        byte2 = n >> NUM_BITS_IN_BYTE;
      }
      else
      {
        byte2 = (unsigned char)n;
        byte1 = n >> NUM_BITS_IN_BYTE;
      }
 
      *currptr++ = byte2;
      *currptr++ = byte1;
 
      return sizeof(unsigned short);
    } /*IsSpaceAvailableForOperation(sizeof(unsigned short)))*/
    err = STREAM_EOF;
    return 0;
  }
 
  //write a unsigned long
  int WriteUnsignedLong(unsigned long n)
  {
    unsigned char byte1, byte2, byte3, byte4;
 
    if ( IsSpaceAvailableForOperation(sizeof(unsigned long)))
    {
      if (endianness == LITTLE_ENDIAN)
      {
        byte1 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte2 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte3 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte4 = (unsigned char)n;
      }
      else
      {
        byte4 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte3 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte2 = (unsigned char)n;
        n >>= NUM_BITS_IN_BYTE;
        byte1 = (unsigned char)n;
      }
 
      *currptr++ = byte4;
      *currptr++ = byte3;
      *currptr++ = byte2;
      *currptr++ = byte1;
 
      return sizeof(unsigned long);
    } /*IsSpaceAvailableForOperation(sizeof(unsigned short)))*/
    err = STREAM_EOF;
    return 0;
  } 
};

Please let me know your comments and suggestions.

Popularity: 5%

16
Jan

Frame Pointer Vs Stack Pointer

Stack look like the below figure, when we are starting in main() and no function is called from
the main() in a C program:

 

 

 



 

 

Suppose, inside of body of main() there’s a call to foo(), which takes two arguments. One way to pass the arguments to foo() is through the stack. When the function foo() is called, the function foo() takes some space in stack for its local variables, hence the stack looks like as below:

 

 

 



 

In the above figure, we notice SP and FP. SP is the stack pointer and FP is the frame pointer. The frame pointer points to the location where the stack pointer was, just before foo() moved the stack pointer for foo()’s own local variables.

Having a frame pointer is convenient when a function is likely to move the stack pointer several times throughout the course of running the function. The idea is to keep the frame pointer fixed for the duration of foo()’s stack frame. The stack pointer, in the meanwhile, can change values.

And, once it’s time to exit foo(), you just have to set the stack pointer to where the frame pointer is, which effectively pops off foo()’s stack frame. It’s quite handy to have a frame pointer.

So when we exit foo() the stack looks just as it did before we pushed on foo()’s stack frame, except this time the return value has been filled in.

 

 

Popularity: 12%

09
Jan

Structure padding explained

What is Padding?
Aligning members of a structre to a byte boundary. Padding is done by compiler to gain the performance. Most hardware architectures
access addresses fast if they are aligned properly, otherwise there will be performance penalty. In order to increase performance compiler pads structures.

How Padding done?
Normally processors require members of the structure aligned to byte boundary, for instance char member(1 byte) should be aligned to
one byte boundary that is it can appear at any byte boundary, a short int(2 bytes) should be aligned to 2 byte boundary that is it should appear at 2 byte boundary, long int(4 bytes) should be aligned to 4 byte boundary. If we declare a basic data type in structure it should appear at sizeof(basic data type) byte boundary, in order to make the start address of the next member at an aligned address.

Example:
Struct X
{
Char a;
Short int b;
Char c;
Long
d;
};

| a(1) | P(1)| b(2) | c(1)| P(3) | d(4) |

P - padding bytes

Why Padding?
If the processor is serious about alignment it raises an exception/signal (ex. SIGBUS), otherwise there will be a performance penalty
will be there as misalignment slowdown data access.

Are members order going to be changed?
ANSI C requires fields of a structure need to allocated in the order they are declared.

As a programmer how does padding matter to me?
It matters if you are concerned about space it takes. By changing the members order of declarations, some amount space can be saved. For example
Struct X
{
Char a;
Long
Int b;
Char c;
Long int d;
Char e;
Long int f;

};

Sizeof(struct X) = 24 bytes

Lets reorder the above structure as below

Struct X
{
Char a;
Char c;
Char e;
Long Int b;
Long int
d;
Long int f;
};

Sizeof(struct X) = 16 bytes

Padding is only done to members or to the structure as a whole
also?

Padding will be done by compiler to structure’s members and to the structure as a whole also. Compiler pads structure as whole because this allows each member of structure aligned in array of structures.

Packed structures
Some compilers provide #pragma to suppress padding or to make it packed to n number of bytes. Some provide keywords to do this.
Generally pragma which is used for modifying structure padding will be in the below format (depends on compiler)
#pragma pack(n)
For example arm
provides __packed keyword to suppress structure padding. Go through your compiler manual to know more about this.

So a packed structure is a structure without padding.
Generally packed structures will be used
->to save space, and
->to format a data structure to transmit over network using some protocol (this is not a good practice of course because you need to deal
with endianness)

How to declare array of packed structures?
We can not declare array of packed structures as for declaring as an array we need each member of structure aligned. So alternatively either we can declare something like this
Struct X
{
Unsigned char a;
Unsigned long b;
}array[NUM_ELEMENTS];

The above structure yields compilation error, if we declare this as below, we should be able to handle..
Unsigned char array_bytes[sizeof(structure) * NUM_ELEMENTS];
And take special care while handling array_bytes.

When I need to be careful about structure padding?
1)when writing structures to a file on one machine and reading them on different machine
This involves problem, consider this example
Struct X
{
Char a;
Long int b;
};

x.a = 0×01;
x.b = 0×02;

If you write struct X to a file, it would have written 0×01 G G G 0×00 0×00 0×00 0×02 (G is garbled value, because this area is padded)
While reading this on different machine(could be big endian) we read the structure as whole, on big-endian these values will be altered and as a result we read corrupted value for member a;
Solution for this would be using a packed structures we can eliminate this.

How can I pack structures Using GCC?
Using the "packed" attribute against the members of a structure. This attribute mechanism is an extension to the GNU C compiler. An example of how you would do this is below.

struct X
{
unsigned char a __attribute__((__packed__));
unsigned
short b __attribute__((__packed__));
unsigned long c
__attribute__((__packed__));
};

Another way to achieve the same is as shown below:
struct X
{
unsigned char a;
unsigned short b;
unsigned long c;
}
__attribute__((__packed__));

How can I pack structures Using ARM compiler?
__packed keyword is used for this purpose, usage is shown below

__packed struct X
{
char a;
Long int b;
};

May be in some other post, I try to give details about how padding done for
global variables, pointers and etc. on some selected machines. Your comments,
suggestions, criticism, etc. most welcome.

Popularity: 39%

06
Jan

c/c++ blogging - January 10, 2007

Welcome to the January 10, 2007 edition of c/c++ blogging.

OpenAsthra presents gettimeofday function for windows posted at OpenAsthra, saying, “gettimeofday function for windows”

OpenAsthra presents Unsigned long to string posted at OpenAsthra, saying, “unsigned long to string program”

OpenAsthra presents PoTerm - A Serial Terminal Shell posted at OpenAsthra, saying, “A serial terminal shell”

OpenAsthra presents dlwrapper: POSIX Wrapper for Windows Dynamic Library loading Calls posted at OpenAsthra, saying, “posix wrapper for windows dynamic library loadinging calls”

OpenAsthra presents Pelt: Posix Wrapper for Windows Threads posted at OpenAsthra, saying, “posix wrapper for windows threads”

OpenAsthra presents OpenAsthra » Blog Archive » Little, Big endianess explained posted at OpenAsthra, saying, “little endian, big edian indetail”

OpenAsthra presents Bad Standard APIs posted at OpenAsthra, saying, “Bad Standard APIs”

OpenAsthra presents Multithreaded Programming using POSIX pthreads — Part 1 posted at OpenAsthra, saying, “Multithreaded Programming using POSIX pthreads — Part 1″

OpenAsthra presents Multithreaded Programming using POSIX pthreads ? Part 2 posted at OpenAsthra, saying, “Multithreaded Programming using POSIX pthreads — Part 2″

OpenAsthra presents Optimizing C and C++ Code posted at OpenAsthra, saying, “Optimizing C and C++ Code”

OpenAsthra presents Questions asked in various job interviews (in Programming) posted at OpenAsthra, saying, “Questions asked in various job interviews (in Programming)”

OpenAsthra presents C/C++ Questions asked in various job interviews posted at OpenAsthra, saying, “C/C++ Questions asked in various job interviews”

Gabe Recchia presents nice type, can i cast you out of it? posted at Gabe Recchia, saying, “A two-second c/c++ chuckle.”

That concludes this edition. Submit your blog article to the next edition of
c/c++ blogging
using our
carnival submission form.
Past posts and future hosts can be found on our

blog carnival index page
.

Technorati tags:

, .

Popularity: 18%

03
Jan

How Bus Error occurs

Today while testing some program I’d encountered this problem. So i’ve digged bit more into it.

The reasons for bus error are

1)accessing unaligned memory addresses: if we are accessing a memory address which is unaligned, this can potentially raise SIGBUS signal on some systems on others this may just slowdown the reading process.

2)accessing a address out of range or non existant address: if the address we are giving is not exist in our enire hardware address range then data bus going to return with error, this will trigger SIGBUS.

3)accessing undefined address: if we try to access undefined address, this may result in segmentation fault

Here is an example which explains the above stuff….

#include <stdio.h>
#include <signal.h>
#include<stdlib.h>

void catchsig(int sig)
{
  if (sig==SIGSEGV)
  {
    printf("segmentation fault\n");
  }
  else if (sig==SIGBUS)
  {
    printf("bus error\n");
  }
}

int main(int argc, char **argv)
{

  char data[sizeof(unsigned long)];
  int *x; int y;

  signal(SIGSEGV, catchsig);
  signal(SIGBUS, catchsig);

  x = (int *)(data + 1);
  y = *x; /*causes bus error on some platforms*/

  x = (int *)0xffffffff /*lets say this address is not in our hardware*/
  y = *x; /*results bus error, as address bus returns with an error*/

  x = (int *)0×100; /*undefined address*/
  y = *x;  /*casues segmentation fault on some machines*/

  return 0;

 

[tags]bus error, SIGBUS, sigmentation fault, sigbus error, sigbus signal, bus errors[/tags]

Popularity: 5%