Search

Sponsored Links

Meta

Categories

Archives

Recent Posts

RSS Feeds

10
Feb

How to distinguish parameter passing techniques?

Before we see what the output of the program shown below is, let us learn how to distinguish two parameter passing techniques: pass by value and pass by address. Keep the following rule in mind:
If the declaration of argument matches the declaration of the formal parameter, then the argument is passed by value. To be more specific, C provides only call-by-value parameter passing.

#include
int main ( void )
{
  char *a =  "abc";
  void f ( char * );   

  f ( a );
  puts ( a );
}   

 void    f ( char *a )
{
   a++;
}

In the above example, the declarations of argument "a", and the formal parameter "a", both are same. That means the variable "a" has been passed by value! But, "a" stands for the address the string, and hence the string has been passed by address. Naturally, only the modification to the object pointed by the pointer (not in this case) has reflection in the main (), but any modification of "a" has no effect. Hence the output of this program is: abc.

Popularity: 5%

06
Feb

Data types in C

The C programming language offers various data types to suit different purposes. They can be broadly categorized as follows:

  • Integral types (char, short, int, long, long long, enum, _Bool)
  • Real floating types (float, double, long double)
  • Complex floating types (float _Complex, double _Complex, long double _Complex)  (New feature
  • void is an empty set of values
  • Derived types (struct type, union type, array type, pointer type,  function type)
  • Incomplete type (array of unknown size, a structure or union of unknown content)

Real and complex floating types are collectively know as floating types; integral and floating types are collectively called arithmetic types; arithmetic and pointer types are collectively called scalar type; arrays and structures are collectively called aggregate types.

Popularity: 11%

06
Feb

Bit swapping - Style II

This program shows a logic of swapping the most significant bit with the least significant bit, second most significant bit with the second least significant bit, and so on.

/*!
* swap-bits.c
* Interchange bits of a byte in the following pattern:
* bit7 <-> bit0
* bit6 <-> bit1
* bit5 <-> bit2
* bit4 <-> bit3
*
*/
#include <stdio.h>
#include <stdlib.h>

#define mask(byte, pos) ((byte) & ~(1<<(pos)))
#define get_bit(byte, pos) ((byte) & (1<<(pos)))
#define program_bit(byte, pos, low_high)    \
        byte = mask(byte, pos);             \
        if (low_high)                       \
            byte  = byte | (1<<pos);

int
main (void)
{
    unsigned char byte = 0×0;
    int i, j;
    int bit_i, bit_j;

    printf("byte: %x\n", byte);
    for(i=0, j=7; i<j; i++, j–)
    {
        bit_i = get_bit(byte, i);
        bit_j = get_bit(byte, j);
        program_bit(byte, i, bit_j);
        program_bit(byte, j, bit_i);
    }
    printf("byte: %x\n", byte);

    return EXIT_SUCCESS;
}

Popularity: 18%

06
Feb

Bit swapping - Style I

This program shows a logic of swapping the most significant bit with the least significant bit, second most significant bit with the second least significant bit, and so on.

/*
* swap_bits.c  -   Swap corresponding bits
*/

/*
*  This program swaps the corresponding bits of a character.  For example,
*          msb (bit 7) is exchanged with lsb (bit 0);
*          msb-1 (bit 6) is exchanged with lsb+a (bit 1), so on
*/

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

unsigned char
swap_bits ( unsigned char uc )
{
    unsigned char bits = 0;
    int times = CHAR_BIT / 2,
          msb = CHAR_BIT-1,
          lsb = 0;

     while ( times– )
     {
        bits |= ( (uc & (1<<msb)) >> msb ) << lsb;
        bits |= ( (uc & (1<<lsb)) >> lsb ) << msb;
        msb–;
        lsb++;
     }
         
    return bits;
}

int
main ( void )
{
    unsigned char uc = 0xef;

    printf ( "The byte: %#x\n", uc );
    printf ( "After bit swapping: %#x\n", swap_bits ( uc ) );
    return EXIT_SUCCESS;
}


Popularity: 15%

06
Feb

Structure padding

What is padding in C?

All modern CPUs expect that the fundamental types — int’s, float’s and long’s — are stored in the memory at their natural boundary; typically, at addresses that are multiples of their length.  Some CPU work efficiently if the memory is properly aligned, and some can work in either case. 

For the following examples, let us assume:

sizeof (int)   == 4
sizeof (char)  == 1
sizeof (float) == 4

When a C compiler processes a structure, it adds padding bit(s)/byte(s), if required, between the members to ensure proper alignment.  Consider the following scenario:

Consider the following structure declaration:

struct pad1
{
int a;
char c;
float f;
};

In the above struct, "a" and "f" should occur at an address multiple of 4, whereas "c" can take any — odd or even — address.  So, the structure appears in the memory as shown:

 ___________________
| a0 | a1 | a2 | a3 |      4-byte alignment
 ——————-       P is padding byte
| c0 | P0 | P1 | P2 |
 ——————-
| f0 | f1 | f2 | f3 |
 ——————-

Consider this structure:

struct pad2
{
float f;
int a;
char c;
};

 ___________________
| f0 | f1 | f2 | f3 |      4-byte alignment
 ——————-       P is padding byte
| a0 | a1 | a2 | a3 |
 ——————-
| c0 | P0 | P1 | P2 |
 ——————-

Following point are worth noting:

  • The compiler also ensures that the structure as a whole appears at an aligned address
  • Padding does NOT occur at the beginning of a structure
  • The value of padding bytes or bits are implementation defined

Uses of padding:

  • Padding is useful, for example, in conforming to externally imposed layouts of machine registers
  • The obvious advantage is efficient access by CPU
  • For some architecture, padding is mandatory as the CPU cannot read misaligned datum.  Usually results a "bus error"

Popularity: 18%

06
Feb

Dynamic width and precision in printf

Consider this statement:

printf("String: %9.8s", str);

Have you ever used printf in the form show above? Do you know how the printf formats this? If no, then read on…

In %9.8s above, 9 specifies minimum width and 8 specifies the precision. Instead of giving absolute numbers, you can use an asterisk, *.

The field width may also be specified by an asterisk, *, in which case an argument of type int is consumed and specifies the minimum width field. The result of specifying a negative width is undefined.

The precision may also be specified by an asterisk following the period, in which case an argument of type int is consumed and specifies the precision. If both the fields width and precision are specified with asterisks, then the field width argument precedes the precision argument.

For example:

#include <stdio.h>
#include <string.h>

/* You calculate this according to your requirement */
#define SOME_VALUE 5

int
main ( void )
{
    char calvin[] = "Calvin and Hobbes";
    char animal[] = "Animal Crackers";

    int width = strlen ( calvin ) + SOME_VALUE;
    int prec = strlen ( calvin )  + SOME_VALUE;

    printf ( "%*.*s\n", width, prec, calvin );
    return 0;
}

Popularity: 4%

« Previous Page