Loading....
Coupon Accepted Successfully!

 

Question 11

Whats wrong with #define myptr int *?



#define myptr int *
myptr p, q;



Only p will be a pointer to an int, and q will just be an int!.


Question 12

What purpose do #if, #else, #elif, #endif, #ifdef, #ifndef serve?


The following preprocessor directives are used for conditional compilation. Conditional compilation allows statements to be included or omitted based on conditions at compile time.


#if
#else
#elif
#endif
#ifdef
#ifndef



In the following example, the printf statements are compiled when the symbol DEBUG is defined, but not compiled otherwise


/* remove to suppress debug printf's*/
#define DEBUG                  
...   
x = ....  

  #ifdef DEBUG   
    printf( "x=%d\n" );  
  #endif...   

y = ....;  

  #ifdef DEBUG   
    printf( "y=%d\n" );  
  #endif...




#if, #else, #elif statements

#if directive

 

  • #if is followed by a intger constant expression.
  • If the expression is not zero, the statement(s) following the #if are compiled, otherwise they are ignored.
  • #if statements are bounded by a matching #endif, #else or #elif
  • Macros, if any, are expanded, and any undefined tokens are replaced with 0 before the constant expression is evaluated
  • Relational operators and integer operators may be used


Expression examples


#if 1
#if 0
#if ABE == 3
#if ZOO  #if ZIP == 'g'
#if (ABE + 2 - 3 * ZIP) > (ZIP - 2)



In most uses, expression is simple relational, often equality test


#if SPARKY == '7' 



#else directive


 

  • #else marks the beginning of statement(s) to be compiled if the preceding #if or #elif expression is zero (false)
  • Statements following #else are bounded by matching #endif


Examples


#if OS = 'A'   
  system( "clear" );
#else   
  system( "cls" );
#endif





#elif directive

 

  • #elif adds an else-if branch to a previous #if
  • A series of #elif's provides a case-select type of structure
  • Statement(s) following the #elif are compiled if the expression is not zero, ignored otherwise
  • Expression is evaluated just like for #if


Examples


#if TST == 1   
  z = fn1( y );
#elif TST == 2   
  z = fn2( y, x );
#elif TST == 3   
  z = fn3( y, z, w );
#endif

...
#if ZIP == 'g'   
  rc = gzip( fn );
#elif ZIP == 'q'   
  rc = qzip( fn );
#else   
  rc = zip( fn );
#endif





#ifdef and #ifndef directives

Testing for defined macros with #ifdef, #ifndef, and defined()


 

  • #ifdef is used to include or omit statements from compilation depending of whether a macro name is defined or not.
  • Often used to allow the same source module to be compiled in different environments (UNIX/ DOS/MVS), or with different options (development/production).
  • #ifndef similar, but includes code when macro name is not defined.


Examples


#ifdef TESTENV   
  printf( "%d ", i );
#endif
#ifndef DOS   
  #define LOGFL "/tmp/loga.b";
#else   
  #define LOGFL "c:\\tmp\\log.b";
#endif




defined() operator


 

  • defined(mac), operator is used with #if and #elif and gives 1 (true) if macro name mac is defined, 0 (false) otherwise.
  • Equivalent to using #ifdef and #ifndef, but many shops prefer #if with defined(mac) or !defined(mac)


Examples


#if defined(TESTENV)   
  printf( "%d ", i );
#endif
#if !defined(DOS)   
  #define LOGFL "/tmp/loga.b";
#else   
  #define LOGFL "c:\\tmp\\log.b";
#endif




Nesting conditional statements

Conditional compilation structures may be nested:

#if defined(UNIX)   
  #if LOGGING == 'y'        
     #define LOGFL "/tmp/err.log"   
  #else       
     #define LOGFL "/dev/null"   
  #endif
#elif defined( MVS )   
  #if LOGGING == 'y'       
     #define LOGFL "TAP.AVS.LOG"   
  #else       
     #define LOGFL "NULLFILE"   
  #endif
#elif defined( DOS )   
  #if LOGGING == 'y'       
     #define LOGFL "C:\\tmp\\err.log"   
  #else       
     #define LOGFL "nul"   
  #endif 
#endif



Question 13

Does the ?: (ternary operator) return a lvalue? How can I assign a value to the output of the ternary operator?


No, it does not return an "lvalue"

Try doing something like this if you want to assign a value to the output of this operator


*((mycondition) ? &var1 : &var2) = myexpression;



Question 14

Can we use variables inside a switch statement? Can we use floating point numbers? Can we use expressions?


No

The only things that case be used inside a switch statement are constants or enums. Anything else will give you a


constant expression required


error. That is something like this is not valid


switch(i)
{
  case 1: // Something; 
          break;
  case j: // Something;
          break;
}




So is this. You cannot switch() on strings


switch(i)
{
  case "string1" : // Something; 
                   break;
  case "string2" : // Something;
                   break;
}





This is valid, however


switch(i)
{
  case 1:     // Something; 
              break;
  case 1*2+4: // Something;
              break;
}



This is also valid, where t is an enum


switch(i)
{
  case 1: // Something; 
          break;
  case t: // Something;
          break;
}



Also note that the default case does not require a break; if and only if its at the end of the switch() statement. Otherwise, even the default case requires a break;


Question 15

What is more efficient? A switch() or an if() else()?


Both are equally efficient. Usually the compiler implements them using jump instructions. But each of them has their own unique advantages.


Question 16

What is the difference between a deep copy and a shallow copy?


Deep copy involves using the contents of one object to create another instance of the same class. In a deep copy, the two objects may contain ht same information but the target object will have its own buffers and resources. the destruction of either object will not affect the remaining object. The overloaded assignment operator would create a deep copy of objects.

Shallow copy involves copying the contents of one object into another instance of the same class thus creating a mirror image. Owing to straight copying of references and pointers, the two objects will share the same externally contained contents of the other object to be unpredictable.
Using a copy constructor we simply copy the data values member by member. This method of copying is called shallow copy. If the object is a simple class, comprised of built in types and no pointers this would be acceptable. This function would use the values and the objects and its behavior would not be altered with a shallow copy, only the addresses of pointers that are members are copied and not the value the address is pointing to. The data values of the object would then be inadvertently altered by the function. When the function goes out of scope, the copy of the object with all its data is popped off the stack. If the object has any pointers a deep copy needs to be executed. With the deep copy of an object, memory is allocated for the object in free store and the elements pointed to are copied. A deep copy is used for objects that are returned from a function.


Question 17

Is 5[array] the same as array[5]?


Yes!

Since array subscripting is commutative in C. That is


array[n] == *((array)+(n)) == *((n)+(array)) == n[array]


But frankly, this feature is of no use to anyone. Anyone asking this question is more or less a fool trying to be cool.


Question 18

What are #pragmas?


The directive provides a single, well-defined "escape hatch" which can be used for all sorts of (nonportable) implementation-specific controls and extensions: source listing control, structure packing, warning suppression (like lint's old /* NOTREACHED */ comments), etc.

For example


#pragma once


inside a header file is an extension implemented by some preprocessors to help make header files idempotent (to prevent a header file from included twice).


Question 19

What is the difference between if(0 == x) and if(x == 0)?


Nothing!. But, it's a good trick to prevent the common error of writing


if(x = 0)


The error above is the source of a lot of serious bugs and is very difficult to catch. If you cultivate the habit of writing the constant before the ==, the compiler will complain if you accidentally type


if(0 = x)


Of course, the trick only helps when comparing to a constant.


Question 20

Should we use goto or not?


You should use gotos wherever it suits your needs really well. There is nothing wrong in using them. Really.

There are cases where each function must have a single exit point. In these cases, it makes much sense to use gotos.


myfunction()
{
  if(error_condition1)
  {
    // Do some processing.
    goto failure;
  }
  
  if(error_condition2)
  {
    // Do some processing. 
    goto failure;
  }

success:
  return(TRUE);

failure:
  
  // Do some cleanup.
  return(FALSE);
}




Also, a lot of coding problems lend very well to the use of gotos. The only argument against gotos is that it can make the code a little un-readable. But if its commented properly, it works quite fine.






Test Your Skills Now!
Take a Quiz now
Reviewer Name