Search

Sponsored Links

Meta

Categories

Archives

Recent Posts

RSS Feeds

04
Nov

Implicit Type Conversions - part 2

Standard Type Conversions

Many C and C++ operators cause implicit type conversions, which change the type of an expression. When you add values having different data types, both values are first converted to the same type. For example, when a short int value and an int value are added together, the
short int value is converted to the int type. It can result in loss of data if the value of the original object is outside the range representable by the shorter type.

Implicit type conversions can occur when:

* An operand is prepared for an arithmetic or logical operation.
* An assignment is made to an lvalue that has a different type than the assigned value.
* A function is provided an argument value that has a different type than the parameter.
* The value specified in the return statement of a function has a different type from the defined return type for the function.

You can perform explicit type conversions using the C-style cast, the C++ function-style cast, or one of the C++ cast operators.

#include <iostream>
using namespace std;
 
int main() {
float num = 98.76;
int x1 = (int) num;
int x2 = int(num);
int x3 = static_cast<int>(num);
 
cout < < "x1 = " << x1 << endl;
cout << "x2 = " << x2 << endl;
cout << "x3 = " << x3 << endl;
}

The following is the output of the above example:

x1 = 98
x2 = 98
x3 = 98

The integer x1 is assigned a value in which num has been explicitly converted to an int with the C-style cast. The integer x2 is assigned a value that has been converted with the function-style cast. The integer x3 is assigned a value that has been converted with the static_cast operator.

User-Defined Conversions

User-defined conversions allow you to specify object conversions with constructors or with conversion functions. User-defined conversions are implicitly used in addition to standard conversions for conversion of initializers, functions arguments, function return values, expression operands, expressions controlling iteration, selection statements, and explicit type conversions.

There are two types of user-defined conversions:

* Conversion by constructor
* Conversion functions

The compiler can use only one user-defined conversion (either a conversion constructor or a conversion function) when implicitly converting a single value. The following example demonstrates this:

class A {
int a_int;
char* a_carp;
public:
operator int() { return a_int; }
operator char*() { return a_carp; }
};
 
class B : public A {
float b_float;
char* b_carp;
public:
operator float() { return b_float; }
operator char*() { return b_carp; }
};
 
int main () {
B b_obj;
//?  long a = b_obj;
char* c_p = b_obj;
}

The compiler would not allow the statement long a = b_obj. The compiler could either use A::operator int() or B::operator float() to convert b_obj into a long. The statement char* c_p = b_obj uses B::operator char*() to convert b_obj into a char* because B::operator char*() hides A::operator char*().

When you call a constructor with an argument and you have not defined a constructor accepting that argument type, only standard conversions are used to convert the argument to another argument type acceptable to a constructor for that class. No other constructors or conversions functions are called to convert the argument to a type acceptable to a constructor defined for that class. The following example demonstrates this:

class A {
public:
A() { }
A(int) { }
};
 
int main() {
A a1 = 1.234;
//? ?  A moocow = "text string";
}

The compiler allows the statement A a1 = 1.234. The compiler uses the standard conversion of converting 1.234 into an int, then implicitly calls the converting constructor A(int). The compiler would not allow the statement A moocow = “text string”; converting a text string to an integer is not a standard conversion.

Conversion by Constructor

A converting constructor is a single-parameter constructor that is declared without the function specifier explicit. The compiler uses converting constructors to convert objects from the type of the first parameter to the type of the converting constructor’s class. The following example demonstrates this:

class Y {
int a, b;
char* name;
public:
Y(int i) { };
Y(const char* n, int j = 0) { };
};
 
void add(Y) { };
 
int main() {
 
// equivalent to
// obj1 = Y(2)
Y obj1 = 2;
 
// equivalent to
// obj2 = Y("somestring",0)
Y obj2 = "somestring";
 
// equivalent to
// obj1 = Y(10)
obj1 = 10;
 
// equivalent to
// add(Y(5))
add(5);
}

The above example has the following two converting constructors:

* Y(int i)which is used to convert integers to objects of class Y.
* Y(const char* n, int j = 0) which is used to convert pointers to strings to objects of class Y.

The compiler will not implicitly convert types as demonstrated above with constructors declared with the explicit keyword. The compiler will only use explicitly declared constructors in new expressions, the static_cast expressions and explicit casts, and the initialization of bases and members. The following example demonstrates this:

class A {
public:
explicit A() { };
explicit A(int) { };
};
 
int main() {
A z;
//?  A y = 1;
A x = A(1);
A w(1);
A* v = new A(1);
A u = (A)1;
A t = static_cast<a>(1);
}</a>

The compiler would not allow the statement A y = 1 because this is an implicit conversion; class A has no conversion constructors.

A copy constructor is a converting constructor.

Conversion Functions

C++You can define a member function of a class, called a conversion function, that converts from the type of its class to another specified type.

-[-class-::] operator–[const][volatile]–conversion_type
-{–function_body–}-

A conversion function that belongs to a class X specifies a conversion from the class type X to the type specified by the conversion_type. The following code fragment shows a conversion function called operator int():

class Y {
int b;
public:
operator int();
};
Y::operator int() {
return b;
}
void f(Y obj) {
int i = int(obj);
int j = (int)obj;
int k = i + obj;
}

All three statements in function f(Y) use the conversion function Y::operator int().

Classes, enumerations, typedef names, function types, or array types cannot be declared or defined in the conversion_type. You cannot use a conversion function to convert an object of type A to type A, to a base class of A, or to void.

Conversion functions have no arguments, and the return type is implicitly the conversion type. Conversion functions can be inherited. You can have virtual conversion functions but not static ones.

Cast Expressions

The cast operator is used for explicit type conversions. This operator has the following form, where T is a type, and expr is an expression:

( T ) expr

It converts the value of expr to the type T. In C, the result of this operation is not an lvalue. In C++, the result of this operation is an lvalue if T is a reference; in all other cases, the result is an rvalue.

C++The remainder of this section pertains to C++ only.

A cast is a valid lvalue if its operand is an lvalue. In the following simple assignment expression, the right-hand side is first converted to the specified type, then to the type of the inner left-hand side expression, and the result is stored. The value is converted back to the specified type, and becomes the value of the assignment. In the following example, i is of type char *.

(int)i = 8? ? ? ? // This is equivalent to the following expression
(int)(i = (char*) (int)(8))

For compound assignment operation applied to a cast, the arithmetic operator of the compound assignment is performed using the type resulting from the cast, and then proceeds as in the case of simple assignment. The following expressions are equivalent. Again, i is of type char *.

(int)i += 8? ? ? ? // This is equivalent to the following expression
(int)(i = (char*) (int)((int)i = 8))

Taking the address of an lvalue cast will not work because the address operator may not be applied to a bit field.

You can also use the following function-style notation to convert the value of expr to the type T. :

expr( T )

A function-style cast with no arguments, such as X() is equivalent to the declaration X t(), where t is a temporary object. Similarly, a function-style cast with more than one argument, such as X(a, b), is equivalent to the declaration X t(a, b).

For C++, the operand can have class type. If the operand has class type, it can be cast to any type for which the class has a user-defined conversion function. Casts can invoke a constructor, if the target type is a class, or they can invoke a conversion function, if the source type is a class. They can be ambiguous if both conditions hold.

An explicit type conversion can also be expressed by using the C++ type conversion operator static_cast.

Example

The following demonstrates the use of the cast operator. The example dynamically creates an integer array of size 10:

#include <stdlib .h>
 
int main(void) {
int* myArray = (int*) malloc(10 * sizeof(int));
free(myArray);
return 0;
}</stdlib>

The malloc() library function returns a void pointer that points to memory that will hold an object of the size of its argument. The statement int* myArray = (int*) malloc(10 * sizeof(int)) does the following

* Creates a void pointer that points to memory that can hold ten integers.
* Converts that void pointer into an integer pointer with the use of the cast operator.
* Assigns that integer pointer to myArray. Because a name of an array is the same as a pointer to the initial element of the array, myArray is an array of ten integers stored in the memory created by the call to malloc().

[tags]standard type conversions, user defined conversion, conversion by constructor[/tags]

Popularity: 5%

04
Nov

Implicit Type Conversions

An expression e of a given type is implicitly converted if used in one of the following situations:

  • Expression e is used as an operand of an arithmetic or logical operation.
  • Expression e is used as a condition in an if statement or an iteration statement (such as a for loop). Expression e will be converted to bool (or int in C).
  • Expression e is used in a switch statement. Expression e will be converted to an integral type.
  • Expression e is used in an initialization. This includes the following:
    • An assignment is made to an lvalue that has a different type than e.
    • A function is provided an argument value of e that has a different type than the parameter.
    • Expression e is specified in the return statement of a function, and e has a different type from the defined return type for the function.

The compiler will allow an implicit conversion of an expression e to a type T if and only if the compiler would allow the following statement:

T var = e;

For example when you add values having different data types, both values are first converted to the same type: when a short int value and an int value are added together, the short int value is converted to the int type.

You can perform explicit type conversions using one of the cast operators, the function style cast, or the C-style cast.

[tags] type casting [/tags]

Popularity: 4%

04
Nov

Program Linkage

Linkage determines whether identifiers that have identical names refer to the same object, function, or other entity, even if those identifiers appear in different translation units. The linkage of an identifier depends on how it was declared. There are three types of linkages: external, internal, and no linkage.

* Identifiers with external linkage can be seen (and refered to) in other translation units.
* Identifiers with internal linkage can only be seen within the translation unit.
* Identifiers with no linkage can only be seen in the scope in which they are defined.

Linkage does not affect scoping, and normal name lookup considerations apply.

[Note] You can also have linkage between C++ and non-C++ code fragments, which is called language linkage. Language linkage enables the close relationship between C++ and C by allowing C++ code to link with that written in C. All identifiers have a language linkage, which by default is C++. Language linkage must be consistent across translation units, and non-C++ language linkage implies that the identifier has external linkage.

Internal Linkage:
The following kinds of identifiers have internal linkage:

* Objects, references, or functions explicitly declared static.
* Objects or references declared in namespace scope (or global scope in C) with the specifier const and neither explicitly declared extern, nor previously declared to have external linkage.
* Data members of an anonymous union.
* C++Function templates explicitly declared static.
* C++Identifiers declared in the unnamed namespace.

A function declared inside a block will usually have external linkage. An object declared inside a block will usually have external linkage if it is specified extern. If a variable that has static storage is defined outside a function, the variable has internal linkage and is available from the point where it is defined to the end of the current translation unit.

If the declaration of an identifier has the keyword extern and if a previous declaration of the identifier is visible at namespace or global scope, the identifier has the same linkage as the first declaration.

External Linkage:

C In global scope, identifiers for the following kinds of entities declared without the static storage class specifier have external linkage:

* An object.
* A function.

If an identifier in C is declared with the extern keyword and if a previous declaration of an object or function with the same identifier is visible, the identifier has the same linkage as the first declaration. For example, a variable or function that is first declared with the keyword static and later declared with the keyword extern has internal linkage. However, a variable or function that has no linkage and was later declared with a linkage specifier will have the linkage that was expressly specified.

In namespace scope, the identifiers for the following kinds of entities have external linkage:

* A reference or an object that does not have internal linkage.
* A function that does not have internal linkage.
* A named class or enumeration.
* An unnamed class or enumeration defined in a typedef declaration.
* An enumerator of an enumeration that has external linkage.
* A template, unless it is a function template with internal linkage.
* A namespace, unless it is declared in an unnamed namespace.

If the identifier for a class has external linkage, then, in the implementation of that class, the identifiers for the following will also have external linkage:

* A member function.
* A static data member.
* A class of class scope.
* An enumeration of class scope.

No Linkage:

The following kinds of identifiers have no linkage:

* Names that have neither external or internal linkage
* Names declared in local scopes (with exceptions like certain entities declared with the extern keyword)
* Identifiers that do not represent an object or a function, including labels, enumerators, typedef names that refer to entities with no linkage, type names, function parameters, and template names

You cannot use a name with no linkage to declare an entity with linkage. For example, you cannot use the name of a class or enumeration or a typedef name referring to an entity with no linkage to declare an entity with linkage. The following example demonstrates this:

int main() {
struct A { };
//?  extern A a1;
typedef A myA;
//?  extern myA a2;
}

The compiler will not allow the declaration of a1 with external linkage. Class A has no linkage. The compiler will not allow the declaration of a2 with external linkage. The typedef name a2 has no linkage because A has no linkage.

Linkage Specifications — Linking to Non-C++ Programs:

C++Linkage between C++ and non-C++ code fragments is called language linkage. All function types, function names, and variable names have a language linkage, which by default is C++.

You can link C++ object modules to object modules produced using other source languages such as C by using a linkage specification. The syntax is:

extern–string_literal–+-declaration

The string_literal is used to specify the linkage associated with a particular function. String literals used in linkage specifications should be considered as case-sensitive. All platforms support the following values for string_literal

“C++”
Unless otherwise specified, objects and functions have this default linkage specification.

“C”
Indicates linkage to a C procedure

Calling shared libraries that were written before C++ needed to be taken into account requires the #include directive to be within an extern “C” {} declaration.

extern “C” {
#include “shared.h”
}

The following example shows a C printing function that is called from C++.

//? in C++ program

extern "C" int displayfoo(const char *);
int main() {
return displayfoo("hello");
}

/*? in C program? ? ? ? */

#include <stdio .h>
extern int displayfoo(const char * str) {
while (*str) {
putchar(*str);
putchar(' ');
++str;
}
putchar('\n');
}</stdio>

[tags]program linkage, internal linkage, external linkage[/tags]

Popularity: 17%

04
Nov

Name Mangling

Name mangling is the encoding of function and variable names into unique names so that linkers can separate common names in the language. Type names may also be mangled. The compiler generates function names with an encoding of the types of the function arguments when the module is compiled. Name mangling is commonly used to facilitate the overloading feature and visibility within different scopes. Name mangling also applies to variable names. If a variable is in a namespace, the name of the namespace is mangled into the variable name so that the same variable name can exist in more than one namespace. The C++ compiler also mangles C variable names to identify the namespace in which the C variable resides.

The scheme for producing a mangled name differs with the object model used to compile the source code: the mangled name of an object of a class compiled using one object model will be different from that of an object of the same class compiled using a different object model. The object model is controlled by compiler option or by pragma.

Name mangling is not desirable when linking C modules with libraries or object files compiled with a C++ compiler. To prevent the C++ compiler from mangling the name of a function, you can apply the extern “C” linkage specifier to the declaration or declarations, as shown in the following example:

extern "C" {
int f1(int);
int f2(int);
int f3(int);
};

This declaration tells the compiler that references to the functions f1, f2, and f3 should not be mangled.

The extern “C” linkage specifier can also be used to prevent mangling of functions that are defined in C++ so that they can be called from C. For example,

extern "C" {
void p(int){
/* not mangled */
}
};

[tags] name mangling, linkage with c functions[/tags]

Popularity: 4%

04
Nov

Writing a simple make file with example

Make :

Automatically detects a piece of code need to be recompiled in a large project.

Ex :

If u have a.c, b.c, c.c in a project and you have modified only b.c then if you build using make

Project then only b.c get compiled.

Pattern of make files:

Target : Prerequisite

command

Ex makefile :

CC=gcc

Exe : a.o b.o

     $(CC) -o exe a.o b.o

a.o : a.c a.h

     $(CC) -c a.c

b.o : b.c b.h

    $(CC) -c b.c

 

Popularity: 3%

04
Nov

C Obscurity Tests (with reasons behind them)

Why char *p=? ponnada? ? ; *p=M dont work? ?

Char *p= “ponnada” ; char *r= “rajulu” ;

*p=M? ; *r=M? ;

p doesnt work where as r works because eventhough p is not a constant variable

the string ? ponnada? stored in .rodata (readonl? y) section, so while modifing

u get an error. R will be stored in stack, so no problems.

But p works on turbo C on windows mechines, so it is not safe to use that way if we need portability, depending

on compiler we may get error.

?

Obscurity Test? :

? ? ? if (? !strcmp(? ponnada? , ? ponnada\0? )) printf(? ..\n? )? ; it prints the dots, coz there is no diff between ? ponnada? and ? ponnada\0? .

? ? ? calloc(2) works? ?? ans? : works but behaviour compiler dependent. Reason? : in C u can pass any number of args, any type of args in a function . if u dont declare a proto u wont even get a warning. Thats why calloc(2) works, calloc takes 2 params (number of items, sizeof item), so here 2 is passed as number of items, size of item will be some junk value, an it tries to allocate

? ? ? int j*=10 works? ?? compilation error

[tags]c obscurity tests[/tags]

Popularity: 4%

04
Nov

Sorting a Linked List

Suppose, we wish to sort the elements of a linked list. We can use any of the standard sorting algorithms for carrying out the sorting. While performing the sorting, when it is time to exchange two elements, we can adopt any of the following two strategies:

Exchange the data part of two nodes, keeping the links intact.

Keep the data in the nodes intact. Simply readjust the links such that effectively the order of the nodes changes.

Of the two methods suggested above, the first one is easier to implement, but the second one is likely to be more efficient. This is because if the data part contains an employee record (containing name, age, salary etc.) then to carry out exchange of this record would be inefficient time wise as well as space wise. In this case, to perform one exchange of records, we need to copy the entire record thrice using the following statements:

struct emp
{
char name ;
int age ;
float salary ;
} temp ;
 
struct empl
{
char name ;
int age ;
float salary ;
struct empl *link ;
} *p, *q ;
 
strcpy ( temp.name, p -> name ) ;
strcpy ( p -> name, q -> name ) ;
strcpy ( q -> name, temp.name ) ;
 
temp.age = p -> age ;
p -> age = q -> age ;
q -> age = temp.age ;
 
temp.sal = p -> sal ;
p -> sal = q -> sal ;
q -> sal = temp.sal ;

Thus a great deal of time would be lost in swapping the records.
Instead if we adopt second method, since we are readjusting only the links this would involve only pointers and not the bulky structures representing records. This limitation can be overcome if we readjust links instead of exchanging data. This has been achieved through the following program.

#include "alloc.h"
struct node
{
int data ;
struct node *link ;
} *start, *visit ;
 
main( )
{
getdata( ) ;
 
printf ( "nLinked List Before Sorting:n" ) ;
displaylist( ) ;
 
selection_sort( ) ;
printf ( "nLinked List After Selection Sorting:n" ) ;
displaylist( ) ;
 
getdata( ) ;
printf ( "nLinked List Before Sorting:n" ) ;
displaylist( ) ;
 
bubble_sort( ) ;
printf ( "nLinked List After Bubble Sorting:n" ) ;
displaylist( ) ;
}
 
getdata( )
{
int val, n ;
char ch ;
struct node *newnode;
newnode = NULL ;
 
do
{
printf ( "nEnter a value: " ) ;
scanf ( "%d", &val ) ;
 
append ( &newnode, val ) ;
 
printf ( "nAny More Nodes (Y/N): " ) ;
ch = getch( ) ;
} while ( ch == 'y' || ch == 'Y' ) ;
start = newnode ;
}
 
/* adds a node at the end of a linked list */
append ( struct node **q, int num )
{
 
struct node *temp ; temp = *q ;
 
if ( *q == NULL ) /* if the list is empty, create first node */
{
*q = malloc ( sizeof ( struct node ) ) ;
temp = *q ;
}
else
{
/* go to last node */
while ( temp -> link != NULL )
temp = temp -> link ;
 
/* add node at the end */
temp -> link = malloc ( sizeof ( struct node ) ) ;
temp = temp -> link ;
}
 
/* assign data to the last node */
temp -> data = num ;
temp -> link = NULL ;
}
 
/* displays the contents of the linked list */
displaylist( )
 
{
visit = start ;
 
/* traverse the entire linked list */
while ( visit != NULL )
{
printf ( "%d ", visit -> data ) ;
visit = visit -> link ;
}
 
}

Here is the selection sort routine

selection_sort( )
{
struct node *p, *q, *r, *s, *temp ;
p = r = start ;
 
while ( p -> link != NULL )
{
s = q = p -> link ;
while ( q != NULL )
{
if ( p -> data > q -> data )
{
if ( p -> link == q ) /* Adjacent Nodes */
{
if ( p == start )
{
p -> link = q -> link ;
q -> link = p ;
temp = p ;
p = q ;
q = temp ;
 
start = p ;
r = p ;
s = q ;
q = q -> link ;
}
else
{
p -> link = q -> link ;
q -> link = p ;
r -> link = q ;
temp = p ;
p = q ;
q = temp ;
s = q ;
q = q -> link ;
}
}
else
{
if ( p == start )
{
temp = q -> link ;
q -> link = p -> link ;
p -> link = temp ;
s -> link = p ;
temp = p ;
p = q ;
q = temp ;
s = q ;
q = q -> link ;
start = p ;
}
else
{
temp = q -> link ;
q -> link = p -> link ;
p -> link = temp ;
r -> link = q ;
s -> link = p ;
temp = p ;
p = q ;
q = temp ;
s = q ;
q = q -> link ;
}
}
}
else
{
s = q ;
q = q -> link ;
}
}
r = p ;
p = p -> link ;
}
 
}

Here is the bubble sort routine…

bubble_sort( )
{
struct node *p, *q, *r, *s, *temp ; s = NULL ;
 
/* r precedes p and s points to the node up to which comparisons are to
be made */
while ( s != start -> link )
{
r = p = start ;
q = p -> link ;
 
while ( p != s )
{
if ( p -> data > q -> data )
{
if ( p == start )
{
temp = q -> link ;
q -> link = p ;
p -> link = temp ;
start = q ;
r = q ;
}
else
{
temp = q -> link ;
q -> link = p ;
p -> link = temp ;
r -> link = q ;
r = q ;
}
}
else
{
r = p ;
p = p -> link ;
}
q = p -> link ;
if ( q == s )
s = p ;
}
}
}

Let us understand the selection_sort( ) and the bubble_sort( ) functions one by one. In selection_sort( ), pointers p and q point to the nodes being compared and the pointers r and s point to the node prior to p and q respectively. Initially, p and r are set to start, where start is a pointer to the first node in the list. Also, to begin with q and s are set to p -> link. The outer loop is controlled by the condition p -> link != NULL and the inner loop is controlled by the condition q != NULL.

While adjusting the links of the nodes being compared, we would encounter one of the following four cases:

Nodes being compared are adjacent to one another and p is pointing to the first node in the list.

Nodes being compared are adjacent to one another and p is not pointing to the first node.

Nodes being compared are not adjacent to one another and p is pointing to the first node.

Nodes being compared are not adjacent to one another and p is not pointing to the first node.

Let us now understand these cases one by one.

Case (a):

When the nodes being compared are adjacent and p is pointing to the first node, the following operations are performed:

p -> link = q -> link ;
q -> link = p ;

temp = p ;
p = q ;
q = temp ;

start = p ;
r = p ;
s = q ;

q = q -> link ;

Case (b):

When the nodes being compared are adjacent and p is not pointing to the first node, the following operations are performed:

p -> link = q -> link ;
q -> link = p ;
r -> link = q ;

temp = p ;
p = q ;
q = temp ;

s = q ;
q = q -> link ;

Case (c):

When the nodes being compared are not adjacent and p is pointing to the first node, the following operations are performed:

temp = q -> link ;
q -> link = p -> link ;
p -> link = temp ;

s -> link = p ;

temp = p ;
p = q ;
q = temp ;

s = q ;
q = q -> link ;
start = p ;

Case (d):
Lastly, when the nodes being compared are not adjacent and p is not pointing to the first node, the following operations are performed:

temp = q -> link ;
q -> link = p -> link ;
p -> link = temp ;

r -> link = q ;
s -> link = p ;

temp = p ;
p = q ;
q = temp ;

s = q ;
q = q -> link ;

If p -> data is not greater than q -> data then the only changes required are:

s = q ;
q = q -> link ;

These statements are simply moving s and q one node down the list. Once the control comes out of the inner loop, we need to move r and p one node down the list.
Now let us understand the bubble_sort( ) function. In bubble_sort( ), p and q point to the nodes being compared, r points to the node prior to the one pointed to by p. Lastly, s is used to point to the node up to which we have to make the comparisons. Initially, p and r are set to start, q is set to p -> link and s is set to NULL. The outer loop is controlled by the condition s != start -> link and the inner loop is controlled by the condition p != s. Now while comparing the nodes there are only two cases to be tackled. These are:

If p is pointing to the first node
If p is not pointing to the first node
In the first case, the assignments that are carried out are given below:

temp = q -> link ;
q -> link = p ;
p -> link = temp ;

start = q ;
r = q ;

On the other hand, when p is not pointing to start, the following operations should be performed:

temp = q -> link ;
q -> link = p ;
p -> link = temp ;

r -> link = q ;
r = q ;

When the condition p -> data > q -> data becomes false, we need to store the address of node currently being pointed to by p in r and then shift p and q one node down the list. In every iteration of the outer loop, the biggest element gets stored at the end. This element naturally should not be used to carry out the comparisons during the next iteration of the outer loop. That is, during every iteration of the outer loop, the inner loop should be executed one time less. The pointer s is used to keep track of the node up to which the comparisons should be made during the next iteration.

[tags]sorting, sorting a linked list, bubble sort, selection sort[/tags]

Disclaimer: this is not my own post, I’d collected information from usenet and other forums, I bear no responsibility for the accuracy and correctness of this content.

Popularity: 28%

04
Nov

Increment(++) and decrement(–) operations

In c : post and pre ++/– gives rvalue as result and takes an lvalue

So, x++++ gives error, next x++ evaluates to rvalue but next ++ operation requires lvalue

In c++ :

Post ++/– gives a rvalue as result

Pre –/++ gives a lvalue as result

So —-x works fine, x++++ doesnt work

X[i]=i++ works ?

Works but behaviour undefined coz we dont know leftside i will evaluated first or right side i evaluated

[tags] increment operation, decrement operation[/tags]

Popularity: 7%

04
Nov

Static volatile const int x=1 valid ?

Yes, x can be changed by system without compilers knowledge, but x cant be modified by program explicitly, and xs scope is limited to that file if x is declared

Outside a function, if it is inside its value will be retained between function calls.

This variable will be stored in data section.

Popularity: 13%

03
Nov

Little, Big endianess explained

Big endian and little endian
"Little Endian" means that the low-order byte of the number is stored in memory at the lowest address, and the high-order byte at the highest address. (The little end comes first.) For example, a 4 byte Long integer

    Byte3 Byte2 Byte1 Byte0

will be arranged in memory as follows:

   Base Address+0  Byte0
   Base Address+1  Byte1
   Base Address+2  Byte2
   Base Address+3  Byte3

Intel processors (those used in PC’s) use "Little Endian" byte order.

"Big Endian" means that the high-order byte of the number is stored in memory at the lowest address, and the low-order byte at the highest address. (The big end comes first.) Our LongInt, would then be stored as:

  Base Address+0  Byte3
  Base Address+1  Byte2
  Base Address+2  Byte1
  Base Address+3  Byte0

Motorola processors (those used in Mac’s) use "Big Endian" byte order.

Which is Better?

You may see a lot of discussion about the relative merits of the two formats, mostly religious arguments based on the relative merits of the PC versus the Mac. Both formats have their advantages and disadvantages.

In "Little Endian" form, assembly language instructions for picking up a 1, 2, 4, or longer byte number proceed in exactly the same way for all formats: first pick up the lowest order byte at offset 0. Also, because of the 1:1 relationship between address offset and byte number (offset 0 is byte 0), multiple precision math routines are correspondingly easy to write.

In "Big Endian" form, by having the high-order byte come first, you can always test whether the number is positive or negative by looking at the byte at offset zero. You don’t have to know how long the number is, nor do you have to skip over any bytes to find the byte containing the sign information. The numbers are also stored in the order in which they are printed out, so binary to decimal routines are particularly efficient.

Ex :

1024 (0×00000400) stored in little endian machine

as

00 00 04 00

in big endian machine stored as

00 04 00 00

is it possible to find endianness at compile time?

no, it is not possible. but we can use compile time flags

ex.

#ifdef _BIG_ENDIAN

//this code

#else

//this code

#endif

How to find endianness by a program

int x=1 ;if(*(char *) &x == 1)

 

printf("little endian") ;

else

pritf("big endian") ;

[tags]big endian, little endian, endianness, embedded system programming[/tags] 

 

Popularity: 35%

Next Page »