I wonder if there is something like a UINT_MAX (= 65535) define in any of the twincat3 system libraries.
I've also never seen them. But you could create them easily as follows
PROGRAM MAIN
VAR
number : UINT;
UINT_MAX : UINT;
END_VAR
UINT_MAX := number - 1;
You could also do it with just a single variable UINT_MAX := UINT_MAX - 1;, but then you have to make sure the 1 only gets subtracted once.
The easiest would be to define them once in a global variable list and make that into a library.
There does not appear to be anything specific inside of TwinCAT that does what you are looking for. There is something similar however inside of the C layer of objects though.
UINT
There are multiple versions of UINT inside the type system (UINT, UINT24, UINT40, UINT48, UINT56) which are all devoted to the same informational range and values.
When viewed inside of the TMC handling (Datatypes), each of these datatypes has 2 properties:
DisplayMinValue: #x0000
DisplayMaxValue: #xFFFF
Implementation and access to these properties appears to be limited to access via the C interface and unavailable from inside TwinCAT itself, but they are there.
Another way around this problem is using the bitwise operator NOT. Define a UINT called UINT_MAX and use the following snippet during the first cycle of the PLC:
UINT_MAX := NOT UINT_MAX;
Related
I have two different variables defined as ^Byte as in:
var
P1 : ^Byte;
P2 : ^Byte;
Yet when I I try:
P1:=P2;
it says Type mismatch yet I can do:
P1:=Pointer(P2);
Coming from C, I don't get it? Wouldn't P1 and P2 be the value of the pointer and when you want to access what it points to you would use P1^ and P2^ and if you use #P1 or #P2 you are getting the address to the pointer variable itself?
What am I missing?
Afaik in classic (70's) standard pascal this should work. But Turbo Pascal adn Delphi and derivatives went a different route, and consider both ^byte's declaration of new separate types.
Solution: declare pbyte = ^byte; and use pbyte everywhere. If you are using a recent Delphi or Free Pascal, pbyte is already predefined or in unit types.
I am writing code in Go to call some of the Windows trust and crypt dlls to verify file signatures. There are many constants in wincrypt.h that I have tried to port over verbatim but i've hit some issues with integer overflow.
For example, all of the error codes that can be returned from WinVerifyTrust are negative values. If I take one example, TRUST_E_NOSIGNATURE, this is defined in winerror.h as so: #define TRUST_E_NOSIGNATURE _HRESULT_TYPEDEF_(0x800B0100L). In my Go code, I have const TRUST_E_NOSIGNATURE = int32(0x800B0100) but when compiled the error is:
constant 2148204800 overflows int32
when I really expected the value to be -2146762496
So, my questions 1) why does it not wrap like it does in other languages 2) Is there anyway to have the constant still use the hex representation of the number or will I have to change the code to const TRUST_E_NOSIGNATURE = int32(-2146762496) which works ok but will require me to make this change in many other constants that I have ported?
You just set it:
const TRUST_E_NOSIGNATURE = int32(-2146762496)
Use hex if you wish:
const TRUST_E_NOSIGNATURE = int32(-0x7ff4ff00)
But for this, you're probably just using the wrong data type. Use a uint32 instead:
const TRUST_E_NOSIGNATURE = uint32(0x800B0100)
why does it not wrap like it does in other languages?
Because it wasn't designed that way. Go follows the philosophy of being as obvious and intuitive as possible. Silent wrapping is very non-intuitive.
uint32_t u32 = 0;
uint16_t u16[2];
static_assert(sizeof(u32) == sizeof(u16), "");
memcpy(u16, &u32, sizeof(u32)); // defined?
// if defined, how to we access the data from here on?
Is this defined behaviour? And, if so, what type of pointer may we use to access the target data after the memcpy?
Must we use uint16_t*, because that suitable for the declared type of u16?
Or must we use uint32_t*, because the type of the source data (the source data copied from by memcpy) is uint_32?
(Personally interested in C++11/C++14. But a discussion of related languages like C would be interesting also.)
Is this defined behavio[u]r?
Yes. memcpying into a pod is well-defined and you ensured that the sizing is the correct.
Must we use uint16_t*, because that suitable for the declared type of u16?
Yes, of course. u16 is an array of two uint16_ts so it must be accessed as such. Accessing it via a uint32_t* would be undefined behavior by the strict-aliasing rule.
It doesn't matter what the source type was. What matters is that you have an object of type uint16_t[2].
On the other hand, this:
uint32_t p;
new (&p) uint16_t(42);
std::cout << p;
is undefined behavior, because now there is an object of a different type whose lifetime has begin at &p and we're accessing it through the wrong type.
The C++ standard delegates to C standard:
The contents and meaning of the header <cstring> are the same as the C standard library header <string.h>.
The C standard specifies:
7.24.1/3 For all functions in this subclause, each character shall be interpreted as if it had the type unsigned char (and therefore every possible object representation is valid and has a different value).
So, to answer your question: Yes, the behaviour is defined.
Yes, uint16_t* is appropriate because uint16_t is the type of the object.
No, the type of the source doesn't matter.
C++ standard doesn't specify such thing as object without declared type or how it would behave. I interpret that to mean that the effective type is implementation defined for objects with no declared type.
Even in C, the source doesn't matter in this case. A more complete version of quote from C standard (draft, N1570) that you are concerned about, emphasis mine:
6.5/6 [...] If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. [...]
This rule doesn't apply, because objects in u16 do have a declared type
What does the :: syntax in Rust, as seen here, mean:
fn chunk(n: uint, idx: uint) -> uint {
let sh = uint::BITS - (SHIFT * (idx + 1));
(n >> sh) & MASK
}
In languages like Haskell it means a type hint, but here the compiler already has an annotation of that values type, so it seems it's likely type casting.
Please review Appendix B: Operators and Symbols of The Rust Programming Language.
In this case, the double colon (::) is the path separator. Paths are comprised of crates, modules, and items.
The full path for your example item, updated for 1.0 is:
std::usize::BITS
Here, std is the crate, usize is a module, and BITS is the specific item — in this case a constant.
If you scroll up in your file, you'll see use core::usize. use adds the path to the set of items to look in. That's how you can get away with just saying usize::BITS. The core crate is an implementation detail of the façade that is the std crate, so you can just substitute std for core in normal code.
:: can also be used as a way to specify generic types when they cannot otherwise be inferred; this is called the turbofish.
See also:
What is the syntax: `instance.method::<SomeThing>()`?
Oops. I wasn't reading very clearly. In this case, it's just the normal way of referring to anything under a module. uint::BITS is a constant, it seems.
I have asked a similar question before, but I realize that I can't make heads or tails of the macrology and templateness. I'm a C (rather than C++) programmer.
What does F() actually do? When does it stuff characters into pgmem (flash)? When does it pull characters out of pgmem? Does it cache them? How does it handle low-memory situations?
There are no templates involved, only function overloading. The F() macro does two things:
uses PSTR to ensure that the literal string is stored in flash memory (the code space rather than the data space). However, PSTR("some string") cannot be printed because it would receive a simple char * which represents a base address of the string stored in flash. Dereferencing that pointer would access some random characters from the same address in data. Which is why F() also...
casts the result of PSTR() to __FlashStringHelper*. Functions such as print and println are overloaded so that, on receiving a __FlashStringHelper* argument, they correctly dereference the characters in the flash memory.
BTW. For the ESP32 library, both of these functions are defined in the following files:
# PSTR : ../Arduino/hardware/espressif/esp32/cores/esp32/pgmspace.h
# F : ../Arduino/hardware/espressif/esp32/cores/esp32/WString.h
And the F(x):
// An abstract class used as a means to provide a unique pointer type
// but really has no body
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
...
Also for ESP32, PSTR(x) is not needed and is just x: #define PSTR(s) (s).