Workshop quiz III (Units 7 and 8)


Answers to the Quiz

1.    (b) 7  9  11  13  15
2.    (c) Nothing
3.    (c) 25
4.    (b) Returns the number of characters in the string
5.    (c) Garbage values
6.    (b) No
7.    (d) Output will be a garbage value
8.    (b) Compile Error
9.    (c) Output is 2.
10.   (d) 2


Explanations and some extra questions

Q.) Predict the output of the following program:

void change( int *b, int n)
{
   int i;
   for( i = 0;  i < n; i++)
            {
         *(b+i) = *(b+i) + 5;
            }
}

int main( )
{
    int a[]={ 2,4,6,8,10 };
    int i;
    change(a,5);
    for( i = 0; i <= 4; i++)
            {
               cout<<“  ”<<a[i];
            }
return 0;
}
 

A.) I don’t think this should pose much of a problem. We are passing the address of the first element of an array to the function (through a pointer). Within the change ( ) function, we modify each element by adding 5 to it. Hence the output will be:

            7  9  11  13  15


Q.) Can you identify what the below program will do? 

void func(int *x, int *y)
{

int *t;
t = x;
x = y;
y = t;

}

int main( )
{

int a=2;
int b=3;
func(&a,&b);
cout<<endl<<a<<" , "<<b;
return 0;

} 

A.) On seeing a temporary variable and assignment statement, people jump to the conclusion that the above program will swap the values of two integers. But this is WRONG. The program actually does nothing.

void func(int *x, int *y)
{

int *t;
t = x;
x = y;
y = t;

}

Within this function, all we are doing is assigning addresses (we are in no way altering ‘a’ or ‘b’). The output will be:

2 , 3

You could swap the values at a particular address (which is what we always do) but here we are simply using the addresses. Hence ‘a’ and ‘b’ are not swapped.


Q.) What is the value of ‘sum’ in the program below:

int getNewValue(int x)
{
            static int div=1;
            return(x/++div);
}

int main( )
{
            int a[]={12,24,45,0,6};
            int i;
            int sum=0;
            for(i = 0; a[i]; i++)
            {
            sum+=getNewValue(a[i]);
            }
            cout<<sum;
            return 0;
}
 

A.) There are a few important points to note in the above program. First of all you should note that we can pass individual array elements to functions as shown in the program above. Secondly, as long as the condition (i.e. the middle expression) in the ‘for’ loop is true (or non-zero), the loop will keep repeating. Thirdly, you should know about static variables and also about the prefix ++ operator. The ‘for loop’ will terminate for the case of a[3] because a[3] is 0. The value of sum will be:

            sum = (12/2) + (24/3) + (45/4) = 25 (because of integer division). 


Q.) Implement the string length function (using pointers).

 A.)

int len(char *str)
{
            int length=0;
            while(*str++!='\0')
            {
                        length++;
            }
            return length;
}
 

            The use of *str++ might seem confusing. ++ has a higher precedence than * (but it’s better to use parentheses to make it clear- the parentheses have been dropped out here just to make the code appear more complex! Some C++ tests might present similar code fragments). Postfix ++ will increment its operand only after the assignment has been done (i.e. it will occur only in the next statement). Thus when * (the dereferencing operator) is applied, we will check whether the character is a null character or not and then we increment the value of ‘str’ (which means ‘str’ will now point to the next character in the string).


Q.) If

            int x = 5;

            int *ptr = &x;

Can we use &x or &ptr as the R-value (left hand side value) of any expression? Justify your answer.

A.) Let’s take a normal assignment expression:

            int y;

            y = 10;

In this case the value 10 is stored in a memory location (which we refer to as ‘y’ in our program). Whenever you perform an assignment, the computer should be able to associate a memory location with the L-value. When ‘y’ is declared, a memory location is allotted for ‘y’ and any later later reference to ‘y’ actually modifies the value at that location. This is why the expression:

            10 = y;

is not legal (10 is a literal and the computer can’t associate any memory address with the L-value). 

Similarly, &x on the left side of an assignment expression is not valid (because &x would yield the address of the variable ‘x’. But where is this value stored?). Similarly, &ptr will produce the address of the pointer but again this is a value which isn’t associated to any memory location. 


Q.) What does the following statement mean:

int ptr;

            *&ptr=10; 

A.) This is a bad method of assigning a value to a variable named ‘ptr’. This tells the compiler that “Obtain the address of the variable ‘ptr’ and store the value of 10 at that location (dereferencing)”. The normal method of writing this is:

            ptr = 10; 


Q.) Why can’t we assign one array to another?

 A.) Let’s say we have 2 integer arrays ‘arr1[5]’ and ‘arr2[10]’. There are many complications involved if C++ permitted us to use:

            arr1 = arr2;

The first obvious problem is what to do with the array sizes?

‘arr1’ actually contains the address of the first element of the array. If the above assignment were permitted, the problem of what should be assigned to arr1 arises. Are we trying to change the base address itself or do we just want to copy the elements from arr2 to arr1? C++ doesn’t support such array assignments.


Q.) In the following code fragment detect the problem: 

int main( )
{
int const max=5;
int ar[max]={1,2,3,4,5};
int *ptr=&ar[0];
for (int i=0;i<max;i++)
{
            *ptr=ar[i] + 5;
            ptr++;
}

for (int i=0;i<max;i++)
{
            cout<<endl<<ptr[i];
}
}

A.) If you are expecting that the output will be 6,7,8,9,10 then you are wrong. Why? ptr was initialized to the address of ar[0]. But within the ‘for’ loop we have kept on incrementing ‘ptr’. Each time the corresponding value at the location is incremented by 5. Once the first loop is complete, ptr is now pointing to the next location beyond ar[4]. Thus in the second loop we are actually displaying garbage values (instead of getting the display of 6,7,8,9,10). If the 2nd loop were:

            for (i=0;i<max;i++)

            {

                        cout<<endl<<ar[i];

            }

then it would be fine.


Q.) Will the following code compile? 

void print(int &x)
{
            cout<<endl<<"Reference";
}

void print(int x)
{
            cout<<endl<<"By value";
}

int main( )
{
            int y=5;
            print(y);
            return 0;
}
 

A.) Without the statement

            print(y);

the code might compile on some compilers. But this statement will produce a compile-time error because the compiler wouldn’t be able to decide which print( ) function to call. Some compilers will flag an error saying “parameter list of print(int) is not sufficiently different from print(int &)”.

And this is logically true since there is no way in which the compiler will know which function to call.


Q.) Is there an error? What would be the output?

class dummy
{
private:
            int data;

public:
            int get_data( )
            {
                        return data;
            }
};

int main( )
{
dummy d1;
cout<<d1.get_data( );
return 0;
}
 

A.) The code will compile and execute even though there is no constructor explicitly defined for the class dummy. The compiler will provide with a default constructor. But some beginners are tempted into believing that a default constructor will initialize all member data. This is not true. The above program will display some undefined (garbage) value. To initialize member data correctly, the class designer should define a constructor and not rely on the implicitly created default constructor.


Q.) In the following class, how can an object use the pointer member ‘ptr’ (how to dereference the pointer and how to assign values)? 

class dummy
{
public:
int *ptr;
};
 

A.) The pointer member can be used as shown in the code fragment below: 

            dummy arr1;
            int i=5;
            arr1.ptr=&i;
            cout<<*(arr1.ptr);

Codes using

            arr1.*ptr

or

arr1.(*ptr)

will not work (they will produce compile errors).

arr1.ptr refers to an address and *(arr1.ptr) dereferences that address to return the value stored at that memory location. 


Q.) Will the following code compile? If it will, what is the output? 

int increment(int &x)
{
            x++;
            return x;
}

int main ( )
{
int y=5;
increment(y)=2;
cout<<y;
return 0;
}

 A.) The compiler will complain at the statement:

increment(y)=2;

saying that increment(y) is not an L-value. The function increment( ) returns an integer which we can use as an R-value, not an L-value. An L-value is one which can be used on the left side of an assignment expression. This in turn means that an L-value should refer in someway to a memory location where a new value can be stored (after the assignment). Thus in the above code fragment, the statement:

increment(y)=2;

is equivalent to writing:

            an-integer-constant=2;

where integer-constant could be anything like 1 or 2 or 3 etc. This is illegal since an integer constant is not a memory location.


Q.) Will the following code compile? If it will, what is the output? 

int& increment(int &x)
{
            x++;
            return x;
}

int main ( )
{
int y=5;
increment(y)=2;
cout<<y;
return 0;
}
 

A.) This will compile since we are returning a reference (and we aren’t returning a reference to a local variable; so the compiler won’t flag a warning). So how does this work and what is the output?

‘y’ is passed as reference to the function increment( ) within which modifying ‘x’ is the same as modifying ‘y’. Thus the value of ‘y’ is incremented to 3. Then we return a reference to x (which is equivalent to returning a reference to ‘y’). Thus the value 2 gets assigned to ‘y’ and the output will be 2.

The point to note is that when a function returns a reference, it can be used as an L-value. 


Q.) What about this code? 

int* increment(int &x)
{
            x++;
            return &x;
}

int main ( )
{
int y=20;
*(increment(y))=2;
cout<<y;
return 0;
}

A.) This is similar to the earlier question except that we are returning a pointer rather than a reference. It will compile and the output is 2.


Q.) Will the code compile? If it will, what is the output? 

class bacteria
{
public:
            static int count;
public:                                       //multiple use of public
            void modify( )
            {
                        count=count+1;
                        cout<<endl<<"The new count is : "<<count;
            }
}; 

int bacteria::count=5;                  

int main( )
{
            bacteria b;
            bacteria::count=1;
            b.modify( );
            return 0;
}

A.) The code will compile (we’ve used ‘public’ twice but this isn’t an error). The output of the code will be 2 (i.e. count will be 2). Since ‘count’ is a public member the statement bacteria::count=1; will modify ‘count’. If ‘count’ were private then the statement would have yielded an error.


Go back to the Contents Page


Copyright © 2005 Sethu Subramanian All rights reserved. Sign my guestbook.