Can some one please explain this code

R

raghukumar

# include <iostream>

class A
{
public:
A() : i(1) {} int i; } ;

class B: public A
{
public :
B(): j(2) {} int j ; } ;

int f(A* p, int count)
{
int total = 0 ;
for (int i=0; i < count ; ++i )
{ total += p->i; }

return (total);
}

int main()
{
std::cout << f(b,10) <<std::endl;
std::cin.get() ;
return 0 ;
}


The output of the above code is 15. But, i expected 10?

Thanks in advance to all..
 
K

Kai-Uwe Bux

raghukumar said:
# include <iostream>

class A
{
public:
A() : i(1) {} int i; } ;

class B: public A
{
public :
B(): j(2) {} int j ; } ;

int f(A* p, int count)
{
int total = 0 ;
for (int i=0; i < count ; ++i )
{ total += p->i; }

return (total);
}

int main()
{
std::cout << f(b,10) <<std::endl;
std::cin.get() ;
return 0 ;
}


The output of the above code is 15.

Nope, the code does not compile because:

std::cout << f(b,10) <<std::endl;
^

The identifier b has no meaning.

But, i expected 10?

The obvious guess would be that the part of the code that you did not show
has undefined behavior.


Best

Kai-Uwe Bux
 
A

Alf P. Steinbach

* raghukumar:
# include <iostream>

class A
{
public:
A() : i(1) {} int i; } ;

class B: public A
{
public :
B(): j(2) {} int j ; } ;

int f(A* p, int count)
{
int total = 0 ;
for (int i=0; i < count ; ++i )
{ total += p->i; }

return (total);
}

int main()
{
std::cout << f(b,10) <<std::endl;
std::cin.get() ;
return 0 ;
}

It may be that my eyes are letting me down, but I fail to see any
definition of the 'b' used in the 'main' function.

So as I see it this code should not compile.

By the way, the indentation above leaves room for positive improvement.

The output of the above code is 15. But, i expected 10?

Since it seems you haven't posted the code you ran, it's difficult to say.

It's always a good idea to check the FAQ before posting.

The FAQ has good advice on how to post a question about Code That Does
Not Work The Way You Expect It To -- check the FAQ.


Cheers, & hth.,

- Alf
 
R

raghukumar

# include <iostream>

class A
{
public:
A() : i(1) {} int i; } ;

class B: public A
{
public :
B(): j(2) {} int j ; } ;

int f(A* p, int count)
{
int total = 0 ;
for (int i=0; i < count ; ++i )
{ total += p->i; }

return (total);

}

int main()
{
std::cout << f(b,10) <<std::endl;
std::cin.get() ;
return 0 ;

}

The output of the above code is 15. But, i expected 10?

Thanks in advance to all..

sorry friends..
# include <iostream>

class A
{
public:
A() : i(1) {} int i; } ;

class B: public A
{
public :
B(): j(2) {} int j ; } ;

int f(A* p, int count)
{
int total = 0 ;
for (int i=0; i < count ; ++i )
{ total += p++->i; }

return (total);

}

int main()
{
B b[10] ;
std::cout << f(b,10) <<std::endl;
std::cin.get() ;
return 0 ;

}


The above is the full code.

thanks ,
 
I

Ian Collins

raghukumar said:
int f(A* p, int count)
{
int total = 0 ;
for (int i=0; i < count ; ++i )
{ total += p++->i; }
p is a pointer to A, p++ increments p by sizeof(A).
return (total);

}

int main()
{
B b[10] ;
std::cout << f(b,10) <<std::endl;

You are passing an array of 10 Bs, a B is bigger than an A.
 
R

raghukumar

You are passing an array of 10 Bs, a B is bigger than an A.

Hey i din't get this part, B is bigger than A agreed, but i am saying

total += p++->i

where i is member variable of A, initialized to 1.
 
J

Joe Greer

Hey i din't get this part, B is bigger than A agreed, but i am saying

total += p++->i

where i is member variable of A, initialized to 1.

When you increment a pointer, it behaves very much like it was
performing
(T *)((char *)p + sizeof(T)). The problem you have is that when you
increment an A* it will add sizeof(A) to the pointer. Your array is of
B's which have a different size than A. So to give a short example of
what is happening. You have:

0: 1
1: 2
2: 1
3: 2

and so on in memory. In this example, the size of A is 1 and the sizeof
B is 2. Your function has no idea that Bs even exist (you pass it an
A*) so as far it it's concerned you have an array of A's. The pointer
will therefore visit the addresses 0, 0 + sizeof(A) = 1, 1 + sizeof(A) =
2, 2 + sizeof(A) = 3 ... This is undefined behavior, but most compilers
won't detect it as such and will happily give you whatever happens to be
in the memory locations visited. In this case, you get 1, 2, 1, 2 ....
And that results 5 1s and 5 2s giving 15. It is only because you only
have the 2 integers in your classes that this isn't just a totally wacky
value. Of course, your machine architecture with have different values
for the sizeof an in and the addresses they exist in, but the behavior
is the same.

HTH
joe
 
R

raghukumar

Hi,
Your function has no idea that Bs even exist (you pass it an
A*) so as far it it's concerned you have an array of A's. The pointer
will therefore visit the addresses 0, 0 + sizeof(A) = 1, 1 + sizeof(A) =
2, 2 + sizeof(A) = 3 ... This is undefined behavior, but most compilers
won't detect it as such and will happily give you whatever happens to be
in the memory locations visited. In this case, you get 1, 2, 1, 2 ....
And that results 5 1s and 5 2s giving 15. It is only because you only
have the 2 integers in your classes that this isn't just a totally wacky
value. Of course, your machine architecture with have different values
for the sizeof an in and the addresses they exist in, but the behavior
is the same.

I was thinking on the same line as mentioned above, and this is what i
realized. Just for testing,
i changed j variable's initial value to 3 in class B. Then ran the
program, as you mentioned instead of getting 1,1,1,1 or 1,2,1,2, it
gave 1,3,1,3(sum=20). This indicates to me that the value which i am
getting as an output, which is 20, is completely depend on how the
internal class structure is stored in memory. But, i don't know what
does standard say anything about this. So, this means can i assume
this behavior is not undefined, as any one at given point in time can
detect the value of the output. If it's really has undefined
behavior, can somebody please show me the right direction, so that i
can get some proof(code), which makes me believe.

Thanks for all your guidance,
 
W

werasm

If it's really has undefined
behavior, can somebody please show me the right direction, so that i
can get some proof(code), which makes me believe.

Thanks for all your guidance,

If you want to use pointer arithmetic, you are bounded
to the actual (base) type. Therefore if you define
an array of B's, the next item is not at (A+1), but
at (B+1). Therefore (A+1) would send you to who knows
where. To prove this, simply change the array to
an array of real A's, otherwise don't use pointer
arithmetic for the traversal (dangerous!).

Code below would give you the correct result.

#include <iostream>

class A
{
public:
A() : i(1) {}
int i;
};

class B : public A
{
public :
B(): j(2)
{}
int j;
};

int f(A* p, int count)
{
int total = 0 ;
for (int i=0; i < count ; ++i )
{
total += p++->i;
}
return (total);
}

int main()
{
A a[10];
std::cout << f(a,10) << std::endl;
std::cin.get() ;
return 0 ;
}
 
J

Joe Greer

I was thinking on the same line as mentioned above, and this is what i
realized. Just for testing,
i changed j variable's initial value to 3 in class B. Then ran the
program, as you mentioned instead of getting 1,1,1,1 or 1,2,1,2, it
gave 1,3,1,3(sum=20). This indicates to me that the value which i am
getting as an output, which is 20, is completely depend on how the
internal class structure is stored in memory. But, i don't know what
does standard say anything about this. So, this means can i assume
this behavior is not undefined, as any one at given point in time can
detect the value of the output. If it's really has undefined
behavior, can somebody please show me the right direction, so that i
can get some proof(code), which makes me believe.

The standard says this is undefined behavior. The object layout is compiler
dependent and there is no guarantees about much of anything. It just happens
give something sensible in your case.

Well, if you want proof that what you are doing is a bad idea, change your j
variable to a double with the value of 30000 and then see what you get.

What you need to do is iterate through B's and that will give you the right answer.
QED.

joe
 
T

Tadeusz B. Kopec

Hey i din't get this part, B is bigger than A agreed, but i am saying

total += p++->i

where i is member variable of A, initialized to 1.

Effect of expression p++, where p is of type A * may be:
1) If p points to an element of array of type A - p will point to next
element of this array (or past the end if before p pointed to the last
element)
2) In any other case it has undefined behaviour.

In your code p doesn't point to an array of A (it's an array of B), so
you have undefined behaviour.
 
R

raghukumar

Hi All,

Well Thanks for your answers, but you know what this question is asked
as one of interview questions, and output was given as 10,15,200,150.
There was no answer which says, undefined behavior, for the first
moment even i had the same impression, but to them what matters is
whether your answer is right/wrong. But any how, this was good
learning point for me.

Thanks,

Regards,
Raghu Kumar K
 
W

werasm

Well Thanks for your answers, but you know what this question is asked
as one of interview questions, and output was given as 10,15,200,150.
There was no answer which says, undefined behavior, for the first
moment even i had the same impression, but to them what matters is
whether your answer is right/wrong.

What about - "none of the above". If this was not option, then
the questionnaire was flawed.

Werner
 
R

raghukumar

What about - "none of the above". If this was not option, then
the questionnaire was flawed.

Well, nothing like this was mentioned. ... :)
only four options..

Thanks,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top