|
mohsen nowruzi wrote:
you can sened your answer to :
mohsennowruzi@gmail.com
or to:
abolfazlk@gmail.com
No way. If you want our help, read our site.
Anyhow, the API calls you want were written AFTER VC6 ( who still uses VC6 ? ) You need to download and install a platform SDK to be able to compile against libraries that include these newer calls.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
I don't know about the SDK thing. I had the same problem before in my BugReporter[^] project, and I found that I just had to set the version number higher for WIN_IE or WINVER (can't remember which) in my stdafx.h file. Certain structs, constants, and functions are preprocessed out if your Internet Explorer and/or Windows version isn't high enough
My articles
www.stillwaterexpress.com
BlackDice
|
|
|
|
|
AND regardless of the 'WINVER or other settings, if the VC6 header files on your syetm are 'old' enough, and plenty of them are using the riginal installation media (even with the SP5 updates), the API is not even declared in the older header files. Thus your need to downlaod the newer platform SDK libraries and header files AND define the WINVER and other definitions sufficiently high enough. It is not always sufficient to only do one or the other of the two tasks.
|
|
|
|
|
I stand corrected. However, the reason I saw it only as the #define 's is because I actually had this problem using VC7! So in my case, I already had the correct header files on my system, but the stdafx.h file that was generated when I started my project didn't add the #define 's correctly. (I'm more asking than telling) Is this correct?
My articles
www.stillwaterexpress.com
BlackDice
|
|
|
|
|
Yes.
VC6 - Download newer Platform SDK and add defines.
VC7 - Just adjust the defines.
At some point, even the VC7 default installation of header files and libraries will be too old, and then it will also need the platform SDK and defines to see the newer API.
Using the recent platform SDK and proper defines, and I can build a VC6 program using all the latest Windows XP API just fine.
|
|
|
|
|
I got a example which could accomplish swap the tow object without needing the temporary object.
here it is
void inplace_swap(int *x, int *y)<br />
{<br />
*x = *x ^ *y; <br />
*y = *x ^ *y; <br />
*x = *x ^ *y; <br />
}
The result is correct, but I want to know the principle behind this '^' operator!
...always look on the <blink>bright
side of life...
(Whistle)
|
|
|
|
|
'^' is the XOR operator, which works bitwise. The result of XOR operator will have the bits ON only where the corresponding bits of the operands are different (i.e. one is ON and other is OFF) and the result will have the bit OFF if the corresponding bits of the operands are same (both ON or both OFF).
If you examine your code, you'll find that ultimately you are doing a
*x = *x ^ *y ^ *x<br />
*y = *x ^ *y ^ *y
XORing anything to itself nullifies the effect, so you are gettning
*x = *y<br />
*y = *x
Regards,
Pravin
|
|
|
|
|
I understand the basic knowledge, but I can't find the regularity!
Here's the output I generated!
(1)00000001^(2)00000010 = (3)00000011
(4)00000100^(6)00000110 = (2)00000010
(8)00001000^(7)00000111 = (15)00001111
(4)00000100^(9)00001001 = (13)00001101
(5)00000101^(7)00000111 = (2)00000010
(2)00000010^(6)00000110 = (4)00000100
(6)00000110^(1)00000001 = (7)00000111
(0)00000000^(2)00000010 = (2)00000010
(6)00000110^(8)00001000 = (14)00001110
(0)00000000^(6)00000110 = (6)00000110
It seems to me that when two operands(integer) XORed together, the outcome is the sum of them. But there are exception such as line 2 ,5 and 6. Why ???
...always look on the <blink>bright
side of life...
(Whistle)
|
|
|
|
|
YongSheng Li wrote:
when two operands(integer) XORed together, the outcome is the sum of them
No, It's not. XORing is different from SUMming. Let's take the example of your second line:
YongSheng Li wrote:
(4)00000100^(6)00000110 = (2)00000010
As I told in the previous post, the last bit in the result is OFF (as both are OFF in operands), the second last bit is ON (as the second last bit of one operand is OFF and that of the other is ON), again the 3rd last bit is OFF(as they both are ON in operands), remaining bits of the result are OFF as they are same (OFF) in both the operands.
If you apply the same logic to all your results, you'll find that there are no exceptions.
P.S. That's why "a^a" is zero, but "a+a" is not.
Regards,
Pravin
|
|
|
|
|
Hello,
I don't think that you know how the XOR works. Take a look at the following table and you'll see the problem:
-----------------------------------
| Param1 | Param2 | Result of XOR |
-----------------------------------
| true | false | true |
| true | true | false |
| false | true | true |
| false | false | false |
-----------------------------------
Hope this helps
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
Later I found out that
doing swap without the temporary object with
void inplace_swap(int *x, int *y)<br />
{<br />
*x = *x ^ *y; <br />
*y = *x ^ *y; <br />
*x = *x ^ *y; <br />
}
is exactly the same with the three statements above that were commented!
So the question is boil down to when will '^' do the subtraction and when addition!
...always look on the <blink>bright
side of life...
(Whistle)
|
|
|
|
|
Why doing such an easy operation so difficult?
Try the following:
void inplace_swap(int* pX, int *pY)
{
*x = *x + *y;
*y = *x - *y;
}
This solution is not perfect in the sense that it can cause integer overflow problems. My assembler is rusty, but you could get around this problem by substracting with carry or something..
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
If I believe that I'm correct, the version with the temporary object, generates less assembler instructions than this version.
If you take a look at the generated machine code, you'll see that what you are trying to do results in less optimal code!
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
why don't you do it that way :
void inplace_swap(int *x, int *y) {
int tmp = *x;
*x = *y;
*y = tmp;
}
TOXCCT >>> GEII power [toxcct][VisualCalc]
|
|
|
|
|
He doesn't want to use the temporary object. I think that the most efficient way is to use the temporary object, but for some reasons, he doesn't want it..
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
I think he just wanted the theory[^] behind the XOR swap.
On smaller processors the XOR swap would actually be faster than a temp variable or having to use a 3rd register if registers were already limited. However, you are correct that the optimization of a temp variable can be faster than the generated XOR swap from a C compiler (and using a modern processor).
void SwapXor(UINT *a, UINT *b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
image00400000+0x1000:
00401000 8b4c2408 mov ecx,[esp+0x8] ; ecx = b
00401004 8b442404 mov eax,[esp+0x4] ; eax = a
00401008 56 push esi
00401009 8b11 mov edx,[ecx] ; edx = *b
0040100b 8b30 mov esi,[eax] ; esi = *a
0040100d 33f2 xor esi,edx ; temp = *a ^ *b
0040100f 8930 mov [eax],esi ; *a = esi(temp)
00401011 8bd6 mov edx,esi ; edx = *a
00401013 8b31 mov esi,[ecx] ; esi = *b
00401015 33f2 xor esi,edx ; temp = *b ^ *a
00401017 8931 mov [ecx],esi ; *b = esi (temp)
00401019 8b10 mov edx,[eax] ; edx = *a
0040101b 8bce mov ecx,esi ; ecx = *b
0040101d 5e pop esi
0040101e 33d1 xor edx,ecx ; temp = *a ^ *b
00401020 8910 mov [eax],edx ; *a = edx(temp)
00401022 c3 ret
void SwapTemp(UINT *a, UINT *b)
{
UINT Temp;
Temp = *a;
*a = *b;
*b = Temp;
}
00401030 8b542408 mov edx,[esp+0x8] ; edx = b
00401034 8b442404 mov eax,[esp+0x4] ; eax = a
00401038 56 push esi
00401039 8b32 mov esi,[edx] ; esi = *b
0040103b 8b08 mov ecx,[eax] ; ecx = *a
0040103d 8930 mov [eax],esi ; *a = esi
0040103f 890a mov [edx],ecx ; *b = ecx
00401041 5e pop esi
00401042 c3 ret
1 million XOR Swap = Milliseconds = 10.569012
1 million Temp Swap = Milliseconds = 4.846916
Generally, it's not the number of instructions that make the difference it's how the assembly is structured. This has no bearing in this case though because you get more instructions and you get slower code as well.
You notice that the memory is read multiple times as well as saved multiple times unnesscarily in the code path. You also notice that there was no "true" temp variable ever generated for the other code so even if you eliminate most of the code it's still not an optimal solution.
So, yes while it may look in C that you are being optimal by not using a "temp" variable, if your compiler is smart enough this doesn't matter and does generate faster code as Bob said. If you are working with embedded systems and are coding the direct assembly, an "xor" approach may work better depending on the situation. It could also work if you hand code assembly for different pipelines where 2 instructions may be executed at the same time. This depends though on if a simple "XCHG" instruction would cause a problem with a pipe "stall" or not.
However, in C I think you can rely on the compiler to optimize with the temp variable rather than atempting to do what is considered a lower level optimization in a higher level language (This is not to say that an "xor" swap is always nessecary in smaller CPUs at all, it's just a possible consideration for certain code optimizations which may or may not be useful. Generally XOR is faster to "set a register to 0" as the most common optimization, XOR EAX, EAX back when a "mov" "MOV EAX, 0" was considered a slow operation. I don't think that's the case any more on newer processors).
8bc7c0ec02c0e404c0cc0680f7018827ebee
|
|
|
|
|
After step 1, *x contains (*x ^ *y) . After step 2, *y contains (*y ^ (*x ^ *y)) , which is just *x . After step 3, *x contains ((*x ^ *y) ^ *x) , which is *y . Make sense? Any number XORed with itself is 0.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
The logic is this:
A = A (operation) B
B = A (operation Inverse) B
A = A (operation Inverse) B
If you do one operation and then two inverse operations you will have swapped the numbers. The "xor" operator is actually the inverse of itself, so that's why it works the way it does.
For example if you use +, - is the inverse:
A = 10, B = 20
A = A + B (10 + 20 = 30)
B = A - B (30 - 20 = 10)
A = A - B (30 - 10 = 20)
A = 20, B = 10
A = 10, B = 20
A = A * B (10*20 = 200)
B = A / B (200/20 = 10)
A = A / B (200/10 = 20)
A = 20, B = 10
A = 10, B = 20
A = A ^ B (10 ^ 20 = 30)
B = A ^ B (30 ^ 20 = 10)
A = A ^ B (30 ^ 10 = 20)
A = 20, B = 10
xor is also communiative, so it didn't matter the order you have A or B when doing ^. This XOR swap was generally used by small processors which memory operations were slow, so 3 XOR instructions could be faster. That actually used to be the method of setting registers to 0 as well, XOR reg, reg as it was faster than a MOV reg, 0.
8bc7c0ec02c0e404c0cc0680f7018827ebee
|
|
|
|
|
So you can think of it as:
1. Combine the numbers together and store in one of the values.
Combined = A + B for example 10 + 20 = 30. In +. But any operation will combine numbers.
2. Inverse, thus if two numbers are combined you will get the opposite number of what you inverse.
Original1 = Combined - B, for example, 30 - 20 = 10. You get the original number.
3. Using the opposite number, now you use the combined number to get the original.
Original2 = Combined - Original1 So you do the inverse again on the new number to get the original.
You can see that if you combine two numbers, you can use those numbers in inverse operations to get the original numbers.
8bc7c0ec02c0e404c0cc0680f7018827ebee
|
|
|
|
|
The Stupid XOR Trick[^]
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" - mYkel - 21 Jun '04
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
Within you lies the power for good - Use it!
|
|
|
|
|
Is there any method found in the IDE of Visual C++ 2003 to remove functions seen in "Class View"? (other than manually delete text in .cpp and .h.)
Thanks!
Maxwell Chen
|
|
|
|
|
Hii alll
how can i change the background of my form????in vc++
thanks
|
|
|
|
|
You can read up on WM_CTLCOLORDLG[^] or you can set it when you register the window class.
Alex Korchemniy
|
|
|
|
|
Look in the CFrame, CMDIFrame, CView, or a class derived from one of these, for some methods to do this. Those classes perform the drawing of the windows and their background. There may be some public members that can be directly set also. My personal guess is a CFrame derived class. I don't remember completely, but you may have to use some API functions to get the pointers to the objects that would need to be changed.
The form background should not be in the App class or the Doc class, since these have to do with running the program and storing the data. I know this does not provide all the answer, but just gives somewhere to start.
David Spain, C++ Applications Programmer
|
|
|
|
|
Hi,
I want add a context menu on a tree (hosted in MFC Dialog), everything wotrk fine unless I do not get the menu draw (only a little strip).
So what's wrong in my code :
CMenu menu;
POINT pp;
GetCursorPos(&pp);
if (menu.LoadMenu(IDR_MENU_TREE))
{
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
pp.x, pp.y,
AfxGetMainWnd()); // use main window for cmds
}
Thanks in advance ...
|
|
|
|
|