what are the problems i am facing?
1. Unable to get exact output due to facing problem in recursion that
too especially when returning the class........
2.I have checked above program for different values before returning,
it is good they are in sorted order, but due to recursion property the
output is mislead.....
That is not the recursion. Method selsort (which could have been a
function as well), takes a copy of an object a1 in the main(), do
something, and return a copy of modified object to the object a1 in the
main()
>
> 2.I have checked above program for different values before returning,
> it is good they are in sorted order, but due to recursion property the
> output is mislead.....
http://www.google.de/search?hl=en&source=hp&q=c%2B%2B+recursion&btnG=Google+Search
------------------------
how do u say that it is not the sorting way, then what i have done
there to sort the values in an array.....
This:
small=small*ptr[i]/(ptr[i]=small);
is not only needlessly obfuscated, but probably also undefined behavior.
(And even if it wasn't, I would never recommend writing such code. Even
after watching it for minutes I can't tell what is it that that line is
trying to do.)
> This:
It's definitely undefined behavior. And like you, I can't
figure out what it's supposed to be---if you separate it into
two expressions:
ptr[ i ] = small ;
small = small * ptr[ i ] / ptr[ i ] ;
it doesn't make much sense, either (especially the last one).
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Hi, sorry again for dropping in out of blue, I just want to understand
this UB thing.
First of all, this line:
small=small*ptr[i]/(ptr[i]=small);
seems just a weird way to swap the variables.
Simplifying the names...
s=s*p/(p=s);
...and being that the / operator associates left to right, i.e it
evaluates "s*p" first and "(p=s)" last, it would give something like:
sp = s*p;
s = sp/(p=s);
Or in other (less clear) "words"...
t = s;
// s=s*p/(p=s); // since "(p=s) == s" this becomes...
// s=s*p/s; // since "s*p/s == p" this becomes...
s = p;
p = t;
Now the question: does the associativity of operators enter in account
when considering the UB issue "evaluated twice in the same expression"
- or whatever it is called?
Francesco
Sorry, I mistaken the meaning of "associativity". But the point
remains, because * and / have the same precedence, they _should_ be
evaluated left to right. So then, is this something to keep in account
when considering the UB issue of sequence points and double
evaluation?
That's quite slippery ground for me :-/
Francesco
Don't forget that line, so you never do anything similar.
I will! Or, in other words, I won't. I won't forget and I won't write
similar stuff ;-)
By the way, I recall having read something about a trick used in
Assembly, where you swap two variables without using a temporary... is
it related to the above expression or to its compilation? I guess they
are completely different things.
Regards,
Francesco
It involves doing three bitwise xor operations. It's completely
counter-productive because the xors will usually be slower, or at most
as fast, as the classical way of swapping.
I would be surprised if the standard required for the left part to be
evaluated before the right part. As long as the result of the expression
is correct, it doesn't matter in which order the elements are evaluated.
So then it is a completely different thing. Thank you for the details,
Juha.
Francesco
Pulling apart that I mistaken the meaning of "association" - because
it involves grouping and not evaluation order - later on I thought
that the two involved operands _ensured_ the evaluation order. Looking
at the operators precedence, I would have said that "(p=s)" _had_ to
be evaluated first, just like James said. The problem is that my GCC
evaluates "s*p" first. And it seems to do so systematically. I'm about
to test it further.
Well, after all I'm not the OP and all of this is just a chance to
learn new things.
Best regards,
Francesco
> > > manohar wrote:
> > > >http://pastebin.com/m4338968e
> > > This:
> > > small=small*ptr[i]/(ptr[i]=small);
> > > is not only needlessly obfuscated, but probably also
> > > undefined behavior. (And even if it wasn't, I would never
> > > recommend writing such code. Even after watching it for
> > > minutes I can't tell what is it that that line is trying
> > > to do.)
> > It's definitely undefined behavior. And like you, I can't
> > figure out what it's supposed to be---if you separate it
> > into two expressions:
> > ptr[ i ] = small ;
> > small = small * ptr[ i ] / ptr[ i ] ;
> > it doesn't make much sense, either (especially the last one).
> Hi, sorry again for dropping in out of blue, I just want to
> understand this UB thing.
In a way, it's pure standardese. The standard uses it whenever,
for whatever reason, it doesn't want to constrain an
implementation. In the concrete case above, for example, it's
highly unlikely that you risk reformatting the hard disk, even
though the standard allows it; on most (maybe all) machines, the
standard could just as easily said that the results of the
expression are unspecified.
> First of all, this line:
> small=small*ptr[i]/(ptr[i]=small);
> seems just a weird way to swap the variables.
But it doesn't swap anything.
> Simplifying the names...
> s=s*p/(p=s);
> ...and being that the / operator associates left to right,
Don't confuse association with order of evaluation. An
expression like a + b + c is (a + b) + c, and not a + (b + c),
but the compiler is still free to evaluate a, b and c in any
order, and to cause any side effects of a, b and c to occur at
any time it wishes before the next sequence point.
> i.e it evaluates "s*p" first and "(p=s)" last,
No.
> it would give something like:
> sp = s*p;
> s = sp/(p=s);
> Or in other (less clear) "words"...
> t = s;
> // s=s*p/(p=s); // since "(p=s) == s" this becomes...
> // s=s*p/s; // since "s*p/s == p" this becomes...
> s = p;
> p = t;
> Now the question: does the associativity of operators enter in
> account when considering the UB issue "evaluated twice in the
> same expression"
> - or whatever it is called?
Associativity controls the results of the expression. Consider:
int i = 1 ;
int j = 3 ;
int k = 100 ;
int x = i * k / j ;
Associativity guarantees that x will be equal to 33, and not 0.
If you replace i, j, and k with functions that return the value,
but have side effects (e.g. int i() { std::cout << 'i' ; return
1 ; }), however, there's absolutely no guarantee with regards to
the order these functions will be called. All associativity
guarantees is that the multiplication will take place before the
division (and thus, will not use the results of the division,
but rather only the results of k).
And it doesn't always work:
template< typename T >
void
swap( T& a, T& b )
{
a ^= b ;
b ^= a ;
a ^= b ;
}
Given this:
char* p1 ;
char* p2 ;
swap( p1, p2 ) ;
doesn't compile. And:
int a = 42 ;
swap( a, a ) ;
compiles, but gives the wrong answer.
Fine, the general UB concept is clear to me, I expressed myself badly.
I meant that I'd like to understand this particular case leading to
UB.
>
> > First of all, this line:
> > small=small*ptr[i]/(ptr[i]=small);
> > seems just a weird way to swap the variables.
>
> But it doesn't swap anything.
Actually, it does swap the variables on my GCC version, see below.
> > Simplifying the names...
> > s=s*p/(p=s);
> > ...and being that the / operator associates left to right,
>
> Don't confuse association with order of evaluation. An
> expression like a + b + c is (a + b) + c, and not a + (b + c),
> but the compiler is still free to evaluate a, b and c in any
> order, and to cause any side effects of a, b and c to occur at
> any time it wishes before the next sequence point.
Yes, I confused them - but I fixed my mistake shortly after. Actually,
seems that the * and / operators enforce some kind of sequence point
on my GCC. See below.
> > i.e it evaluates "s*p" first and "(p=s)" last,
>
> No.
As I said above, it does so, on my GCC.
[ associativity details snipped, thanks for the clarification ]
Given the standard specifications, the fact that the following code...
-------
#include <iostream>
using namespace std;
int A(){cout << "A"; return 1;}
int B(){cout << "B"; return 1;}
int C(){cout << "C"; return 1;}
int main()
{
A() * B() / C();
cout << endl;
A() * (B()) / ((C()));
cout << endl;
int s = 1;
int p = 2;
cout << "s==" << s << " p==" << p << endl;
s=s*p/(p=s);
cout << "s==" << s << " p==" << p << endl;
return 0;
}
-------
...produces this output...
-------
ABC
ABC
s==1 p==2
s==2 p==1
-------
...must be considered pure luck or expected result? I mean it in
particular, related to the use of the * and / operators and related to
the fact that the variables get actually swapped.
Francesco
Heck, the response was in the part I snipped. Sorry, James.
Hence the above result must be pure luck, swapping included.
Francesco
Hi manohar, since some problems in your code haven't been pointed out,
I'm taking the occasion to point them out and to resume the thread for
your convenience.
First, this is your code as taken from the link you mentioned:
-------
//selection sort using recursive using class
#include<iostream.h>
#include<conio.h>
class selrec
{
int small,i,n,a[10];
public:
void accept();
selrec selsort(selrec,int );
void display();
}a1;
void selrec::accept()
{
cout<<"\nEnter how many elements: ";
cin>>n;
cout<<"\nEnter the elements: ";
for(i=0;i<n;i++)
cin>>a[i];
}
selrec selrec::selsort(selrec x,int j)
{
int *ptr=&x.a[j];
small=ptr[0];
for(i=1;i<x.n;i++)
if(small>ptr[i])
small=small*ptr[i]/(ptr[i]=small);
ptr[0]=small;
//cout<<" "<<ptr[0];
if(x.n!=1)
{
--x.n;
++j;
selsort(x,j);
}
return x;
}
void selrec::display()
{
cout<<"\nsorted elements are: ";
for(i=0;i<n;i++)
cout<<" "<<a[i];
}
void main()
{
clrscr();
a1.accept();
a1=a1.selsort(a1,0);
a1.display();
}
-------
- Vladimir Jovic suggested you to change the "selsort()" function
because it's needlessly declared as a member function. Either change
the internal implementation or implement it as a separate function.
Vladimir also pointed out a link with which you can get pointers about
the algorithm you want to implement. Read some of the resources
pointed out and rewrite your algo.
- You're swapping the variables with an expression that counts on luck
- that statement is undefined behavior as pointed out by Juha Nieminen
and James Kanze. Add a temporary and do the swap in the right way.
- You've declared a class member "i" that you're using as a local
counter for the "for" loops. Don't do that. Instead, declare it each
time in each "for" loop. The same stands for the other variables.
Declare them in the smallest possible scope and initialize them as
soon as possible - in your case, that would be immediately, in the
declaration.
- You've declared a class member "a[10]" and your "accept()" function
can write outside of its boundaries. Don't use arrays, use
std::vector.
- Read the clc++ FAQ http://www.parashift.com/c++-faq-lite and fix the
other weird things of your code (not-conforming main, superfluous non-
STD headers and function call, standard header included in the ".h"
form and namespace qualifications missing).
Once you have fixed all the above, shall you need again, post the code
and we'll have a look to see what is going wrong - you current
implementation simply doesn't work, I've just compiled it and fed it
"5" as number of elements, "5 4 3 2 1" as elements and it returned "1
5 4 3").
The next time, post the code directly in your message and not
elsewhere on the net, where your code could disappear at any moment,
also give meaningful names to the important variables, so that people
reading your code can understand what they are meant to represent.
You might want to take my points upside-down and start by reading the
FAQ. Take it from the beginning and dig your way through it as much as
you can. You'll learn a lot of things.
Keep on improving your code,
best regards,
Francesco
Just because gcc happens to do it that way doesn't mean that it
couldn't do it in some other way, while still being fully
standard-compliant.
> Given the standard specifications, the fact that the following code...
[...]
> ...must be considered pure luck or expected result?
You can expect your version of gcc to do that, but you can't expect
every single standard-compliant C++ compiler in existence to do it in
the same way. (Technically speaking you can't even expect for the next
version of gcc to do it in the same way, even though it's unlikely it
will change.)
In other words, if you want your program to be fully portable, you
can't make that assumption.
I assume that means that if you have overloaded operator* and
operator/, the standard guarantees that the former will be called before
the latter (even though the order in which the parameters are evaluated
is not guaranteed)?
Never said otherwise. Mine was a relative assertion, not an absolute
one, please read below.
> > Given the standard specifications, the fact that the following code...
> [...]
> > ...must be considered pure luck or expected result?
>
> You can expect your version of gcc to do that, but you can't expect
> every single standard-compliant C++ compiler in existence to do it in
> the same way. (Technically speaking you can't even expect for the next
> version of gcc to do it in the same way, even though it's unlikely it
> will change.)
>
> In other words, if you want your program to be fully portable, you
> can't make that assumption.
Of course. My question started with "Given the standard
specifications...", and was related to the (eventual) mandated
behavior.
Mentioning my GCC was just to report a compiler where the "weird way
of swapping variables" worked. Nothing more than that.
Best regards,
Francesco
> Francesco wrote:
>>>> i.e it evaluates "s*p" first and "(p=s)" last,
>>> No.
>>
>> As I said above, it does so, on my GCC.
>
> Just because gcc happens to do it that way doesn't mean that it
> couldn't do it in some other way, while still being fully
> standard-compliant.
>
>> Given the standard specifications, the fact that the following code...
> [...]
>> ...must be considered pure luck or expected result?
>
> You can expect your version of gcc to do that, but you can't expect
> every single standard-compliant C++ compiler in existence to do it in
> the same way. (Technically speaking you can't even expect for the next
> version of gcc to do it in the same way, even though it's unlikely it
> will change.)
Such things are known to change just by altering the optimization level,
no need to wait for the next gcc version ;-)
Paavo