Discussion about development of draughts in the time of computer and Internet.
-
TAILLE
- Posts: 968
- Joined: Thu Apr 26, 2007 18:51
- Location: FRANCE
Post
by TAILLE » Mon Jun 25, 2018 15:20
Hi,
The purpose of this post is to share potential coding issues.
Code: Select all
#define mask 0x80000000
INT64 x = 0xffffffffffffffff;
x &= ~mask;
I expected the result 0xffffffff7fffffff but with my compilor the result is 0x000000007fffffff
No problem if mask = 0x40000000 or mask = 0x100000000.
Obviously the problem occur when the ~ operator change a negative 32 bits value into a positive one.
In order to solve the problem I wrote
#define mask (INT64)0x80000000
Do you have similar results with your compilator?
Gérard
-
Fabien Letouzey
- Posts: 299
- Joined: Tue Jul 07, 2015 07:48
- Real name: Fabien Letouzey
Post
by Fabien Letouzey » Mon Jun 25, 2018 15:34
Hi Gérard,
TAILLE wrote:INT64 x = 0xffffffffffffffff;
No matter how many digits you put, this is a (signed) 32-bit literal. You need to append ULL (or ui64 for MS compilers) to extend that. "1 << 32" would fall into the same trap (although the compiler is allowed to do the right thing in this case), etc ...
Don't get me wrong: your code and my example should work in a well-designed language; after all, it should be the same as maths. It's just that C and C++ have a different view of our code.
Fabien.
-
Rein Halbersma
- Posts: 1722
- Joined: Wed Apr 14, 2004 16:04
-
Contact:
Post
by Rein Halbersma » Mon Jun 25, 2018 20:07
Fabien Letouzey wrote:Hi Gérard,
TAILLE wrote:INT64 x = 0xffffffffffffffff;
No matter how many digits you put, this is a (signed) 32-bit literal. You need to append ULL (or ui64 for MS compilers) to extend that. "1 << 32" would fall into the same trap (although the compiler is allowed to do the right thing in this case), etc ...
Don't get me wrong: your code and my example should work in a well-designed language; after all, it should be the same as maths. It's just that C and C++ have a different view of our code.
Fabien.
The real problem is the macro which operates completely outside the type system. Just use a constexpr variable with the type you want:
Code: Select all
#include <cstdint>
#include <iostream>
constexpr uint64_t mask = 0x80000000;
int main() {
uint64_t x = 0xffffffffffffffff;
x &= ~mask;
std::cout << std::hex << x;
}
Online example
-
TAILLE
- Posts: 968
- Joined: Thu Apr 26, 2007 18:51
- Location: FRANCE
Post
by TAILLE » Mon Jun 25, 2018 21:37
Rein Halbersma wrote:Fabien Letouzey wrote:Hi Gérard,
TAILLE wrote:INT64 x = 0xffffffffffffffff;
No matter how many digits you put, this is a (signed) 32-bit literal. You need to append ULL (or ui64 for MS compilers) to extend that. "1 << 32" would fall into the same trap (although the compiler is allowed to do the right thing in this case), etc ...
Don't get me wrong: your code and my example should work in a well-designed language; after all, it should be the same as maths. It's just that C and C++ have a different view of our code.
Fabien.
The real problem is the macro which operates completely outside the type system. Just use a constexpr variable with the type you want:
Code: Select all
#include <cstdint>
#include <iostream>
constexpr uint64_t mask = 0x80000000;
int main() {
uint64_t x = 0xffffffffffffffff;
x &= ~mask;
std::cout << std::hex << x;
}
Online example
Hi Rein,
Seeing your post I don't know if you see a problem with the macro I proposed i.e.
#define mask (INT64)0x80000000
if you think using a constexpr approach is a better approach, what is your point?
Gérard
-
Rein Halbersma
- Posts: 1722
- Joined: Wed Apr 14, 2004 16:04
-
Contact:
Post
by Rein Halbersma » Tue Jun 26, 2018 08:59
TAILLE wrote:Rein Halbersma wrote:
The real problem is the macro which operates completely outside the type system. Just use a constexpr variable with the type you want:
Code: Select all
#include <cstdint>
#include <iostream>
constexpr uint64_t mask = 0x80000000;
int main() {
uint64_t x = 0xffffffffffffffff;
x &= ~mask;
std::cout << std::hex << x;
}
Online example
Hi Rein,
Seeing your post I don't know if you see a problem with the macro I proposed i.e.
#define mask (INT64)0x80000000
if you think using a constexpr approach is a better approach, what is your point?
Jonathan Wakely (maintainer of the gcc C++ Standard Library) gave an answer to this on StackOverflow:
https://stackoverflow.com/questions/423 ... -vs-macros
-
TAILLE
- Posts: 968
- Joined: Thu Apr 26, 2007 18:51
- Location: FRANCE
Post
by TAILLE » Tue Jun 26, 2018 14:14
Rein Halbersma wrote:TAILLE wrote:Rein Halbersma wrote:
The real problem is the macro which operates completely outside the type system. Just use a constexpr variable with the type you want:
Code: Select all
#include <cstdint>
#include <iostream>
constexpr uint64_t mask = 0x80000000;
int main() {
uint64_t x = 0xffffffffffffffff;
x &= ~mask;
std::cout << std::hex << x;
}
Online example
Hi Rein,
Seeing your post I don't know if you see a problem with the macro I proposed i.e.
#define mask (INT64)0x80000000
if you think using a constexpr approach is a better approach, what is your point?
Jonathan Wakely (maintainer of the gcc C++ Standard Library) gave an answer to this on StackOverflow:
https://stackoverflow.com/questions/423 ... -vs-macros
Just a question for clarification.
When you use a constexpr does that mean that a memory word is used in memory? As a consequence does that mean less speed for your program due to the memory access to this constant?
Gérard
-
Rein Halbersma
- Posts: 1722
- Joined: Wed Apr 14, 2004 16:04
-
Contact:
Post
by Rein Halbersma » Tue Jun 26, 2018 16:54
TAILLE wrote:Rein Halbersma wrote:TAILLE wrote:
Hi Rein,
Seeing your post I don't know if you see a problem with the macro I proposed i.e.
#define mask (INT64)0x80000000
if you think using a constexpr approach is a better approach, what is your point?
Jonathan Wakely (maintainer of the gcc C++ Standard Library) gave an answer to this on StackOverflow:
https://stackoverflow.com/questions/423 ... -vs-macros
Just a question for clarification.
When you use a constexpr does that mean that a memory word is used in memory? As a consequence does that mean less speed for your program due to the memory access to this constant?
The variable is typically stored in memory, but the access is substituted at the place-of-call by the compiler whenever it knows that at compile-time (i.e. in other constant expressions). So masking a runtime bitboard of kings with a constexpr mask does not cost a memory access.
-
TAILLE
- Posts: 968
- Joined: Thu Apr 26, 2007 18:51
- Location: FRANCE
Post
by TAILLE » Tue Jun 26, 2018 17:40
Rein Halbersma wrote:TAILLE wrote:
Just a question for clarification.
When you use a constexpr does that mean that a memory word is used in memory? As a consequence does that mean less speed for your program due to the memory access to this constant?
The variable is typically stored in memory, but the access is substituted at the place-of-call by the compiler whenever it knows that at compile-time (i.e. in other constant expressions). So masking a runtime bitboard of kings with a constexpr mask does not cost a memory access.
Now I understand your point.
Thank you Rein
Gérard
-
Rein Halbersma
- Posts: 1722
- Joined: Wed Apr 14, 2004 16:04
-
Contact:
Post
by Rein Halbersma » Wed Jun 27, 2018 00:01
TAILLE wrote:Rein Halbersma wrote:TAILLE wrote:
Just a question for clarification.
When you use a constexpr does that mean that a memory word is used in memory? As a consequence does that mean less speed for your program due to the memory access to this constant?
The variable is typically stored in memory, but the access is substituted at the place-of-call by the compiler whenever it knows that at compile-time (i.e. in other constant expressions). So masking a runtime bitboard of kings with a constexpr mask does not cost a memory access.
Now I understand your point.
Thank you Rein
It just so happened that the Microsoft Visual C++ Team blogged about this very topic today! The occasion: release of VS 2017 15.8 preview 3
https://blogs.msdn.microsoft.com/vcblog ... constexpr/
-
Jelle Wiersma
- Posts: 67
- Joined: Wed Aug 12, 2015 17:45
- Real name: Jelle Wiersma
Post
by Jelle Wiersma » Wed Jun 27, 2018 20:29
Hi Gérard,
I would recommend using const which is not allocated in memory, but is followed by a type such that the compiler can perform type checking.
Also I would recommend to use unsigned integers when doing bit mask operations. Actually this is more-or-less a must when you start to shift bits in case of bitboards, otherwise the high bit, which is used for the sign in signed integers, will not shift like the other bits.
Jelle
-
TAILLE
- Posts: 968
- Joined: Thu Apr 26, 2007 18:51
- Location: FRANCE
Post
by TAILLE » Wed Jun 27, 2018 21:26
Jelle Wiersma wrote:Hi Gérard,
I would recommend using const which is not allocated in memory, but is followed by a type such that the compiler can perform type checking.
Also I would recommend to use unsigned integers when doing bit mask operations. Actually this is more-or-less a must when you start to shift bits in case of bitboards, otherwise the high bit, which is used for the sign in signed integers, will not shift like the other bits.
Jelle
I agree with you Jelle.
I will go through all my macros in order to improve the security of my program by introducing const.
Thank you all.
Gérard