Thursday, December 3, 2009

Extern keyword

1)
main()
{
extern int i;
i=20;
printf("%d",sizeof(i));
}
Answer:
Linker error: undefined symbol '_i'.
Explanation:
extern declaration specifies that the variable i is defined somewhere else.
The compiler passes the external variable to be resolved by the linker. So
compiler doesn't find an error. During linking the linker searches for the
definition of i. Since it is not found the linker flags an error.
2)
main()
{
printf("%d", out);
}
int out=100;
Answer:
Compiler error: undefined symbol out in function main.

Explanation:
The rule is that a variable is available for use from the point of declaration.
Even though a is a global variable, it is not available for main. Hence an
error.
3)
main()
{
extern out;
printf("%d", out);
}
int out=100;
Answer:
100
Explanation:
This is the correct way of writing the previous program.

Using ## and # with define.

Stringize(#)

#define   message_for(a, b)  \
printf(#a " and " #b)
int main()
{
message_for(Carole, Debra);
}

Token pasting (##)
#define f(g,g2) g##g2
main()
{
int var12=100;
printf("%d",f(var,12));
}
Answer:
100

Return values of some functions in c

scanf

scanf("%d" , & i); //10 is given as input

Scanf returns number of items successfully read and not 1/0. Here 10 is given as input which should have been scanned successfully. So number of items read is 1.

printf
Upon a successful return, the printf() function returns the number of characters printed (not including the trailing '\0' used to end output to strings). If the output was truncated due to this limit then the return value is the number of characters (not including the trailing '\0') which would have been written to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated. If an output error is encountered, a negative value is returned.
eg.
#include
int main()
{
int i=448;
printf("%d\n",printf("%d",printf("%d",i))); return 0;
}

Output: 44831
We proceed from right to left ... 1st 448 is printed, that has 3 characters, than 3 is printed and finally as 3 is 1 digit no. we print 1
alternatively if we use the string :
printf("%d\n",printf("%d a ",printf("%d b ",i)));
Output: 448 b 6 a 4
Now we have to count 448+1 space + b+1 space = 6 characters 
6 +1 space + a + 1 space = 4

The preprocessor directives can be redefined anywhere in the program

#include
#define a 10
main()
{
#define a 50
printf("%d",a);
}
Answer:
50
Explanation:
The preprocessor directives can be redefined anywhere in the program. So
the most recently assigned value will be taken.

Graphics questions

the anti-aliasing technique which allows shift of 1/4, 1/2 and 3/4 of a pixel diameter enabling a closer path of a line is

1. pixel phasing
2. filtering
3. intensity compensation
4. sampling technique


Ans 3 

the process of transforming one bit pattern intothe process of transforming one bit pattern into
another by bit-wise operations is called

1. masking 2. pruning
3. biting 4. chopping
  

Ans 3
1. masking
    is AND operation to convert a preknown number of digits to 0
    if these are the bits    101100110 and if 4 LSBs are to masked AND it with 111110000

2. pruning
   to delete cetain bits.
3. biting
    ANS
4. chopping
   to remove a certain number of bits

Sorting Techniques

Basic Mathematics in Algorithms

Recurrence Relations

Recurrence relations often arise in calculating the time and space complexity of algorithms. The amount of time (or space) that a program takes, Tk, is typically a function of the size, k, of the input data. A recurrence relation arises when Tk is some function of Tk' for k'
Logarithmic Complexity

The following recurrence

Tk = Tk/2 + a if k!=1
= b if k=1

has the solution

Tn = a*log2(n) + b

when n is a power of 2. The solution should be no surprise because when the problem size is doubled from k/2 to k the resource used only increase by a constant a. Repeated doubling, i.e. 1, 2, 4, 8, 16, 32, ..., reaches any limit n in about log2(n) steps. Unless otherwise stated, logarithms are to base two.

The mathematical proof of the solution by induction has two stages. First the base case for k=1 is shown to be a particular case of the general solution. Secondly, assuming the solution up to n/2, it is then shown to hold for the next value, n.

(i) T1 = a*log 1 + b
= b
(ii) Tn = Tn/2 + a
= (a*log(n/2) + b) + a
= a*(log n - log 2) + b + a
= a*log n + b

The binary-search algorithm over n (sorted) objects has this time-complexity. It is a very good complexity to have because Tn grows only slowly as n gets large.
Linear Complexity

The solution of the following recurrence

Tk = b + Tk-1 if k~=1
= a if k=1


can be found as follows

Tn = b + Tn-1
= b + (b+Tn-2)
= 2b + Tn-2
...
= (n-1)b + T1
= (n-1)b + a
= n*b + (a-b)

Many linear-algorithms, linearly-recursive or iterative, have this time-complexity. See the section on linear search. While not as good as logarithmic complexity, linear complexity is somehow "fair": double the size of the problem and the algorithm uses twice as much resource.
Exponential Complexity

A third class of algorithms has complexity given by the following recurrence relation.

Tk = 2*Tk-1 + a if k~=0
= b if k=0


The solution for Tn is:

Tn = (a+b)*2n-a

The solution is by induction:

(i) T0 = (a+b)*20 -a
= (a+b)-a
= b

(ii) Tn = 2*Tn-1+a

= 2*((a+b)2n-1-a)+a

= (a+b)*2n - a

Many binary-recursive procedures have this time-complexity; see for example the (slow) Fibonacci routine. Exponential complexity grows very rapidly indeed with the size of the problem. Just adding one to the problem size causes the complexity to roughly double. If a problem requires algorithms with this complexity and the problem size is large then its solution by computer may be possible in principle but infeasible in practice. 


Notation

f is O(g) iff
there are positive constants k and m s.t. 0≤f(n)≤k*g(n) for all n≥m. i.e. f grows no more rapidly than g, in the long run, give or take a multiplicative constant.
f is Ω(g) iff
there are positive constants k and m s.t. f(n)≥k*g(n)≥0 for all n≥m; equivalently g(n)≤(1/k)*f(n) so g is O(f). i.e. f grows at least as quickly as g, in the long run, give or take a multiplicative constant.
f is Θ(g) iff
f is O(g) and f is Ω(g), or equivalently f is O(g) and g is O(f). i.e. f and g grow at the same rate, in the long run, give or take a multiplicative constant.
f is o(g) iff
f is O(g) and f is not Θ(g). i.e. f grows strictly more slowly than g, in the long run, give or take a multiplicative constant.