In HAL library used in the STM32 code we see that a style like this is used:
#define I2C1 ((I2C_TypeDef *) I2C1_Base)
Why define is used like this?
Why pointer type is used?
Why isn't the star outside the parentheses?
I2C1_Base is declared elsewhere, and is a number as a hex literal.
(I2C_TypeDef *) casts the I2C1_Base number to a pointer to an I2C_TypeDef, the star needs to be within the parenthesis as it's casting to a pointer type, if it were outside then it would be a dereference and wouldn't compile.
The define is there to allow code like
I2C1->someRegister = 0xf00;
rather than needing to manually type the cast each time.
Related
Motivation is trying to use a callback with a C API where I pass in anything I want through a void pointer.
So suppose I have an x: UnsafePointer<Void>. I know what it really is, so I want to convert the pointer appropriately. What is the difference between using unsafeBitCast, or just applying UnsafePointer to x? In other words
Is
let y = unsafeBitCast(x, to: UnsafePointer<MyStruct>.self)
different from
let z = UnsafePointer<MyStruct>(x)
in some way?
unsafeBitCast is an unsafe conversion between any two Swift types of the same size. That is, you can write unsafeBitCast(x, UnsafePointer<MyStruct>.self), but you could have also written unsafeBitCast(x, MyClass.self) or unsafeBitCast(x, Int.self). This is generally very unsafe, because Swift doesn't guarantee much about the memory layout of its types. Using UnsafePointer or Unmanaged might be better options in your case.
The "coercion" UnsafePointer<MyStruct>(x) isn't really a special language feature, it's just an UnsafePointer initializer which takes another UnsafePointer. Its effect is to reinterpret the value at the same memory address as a different type, similar to casting between pointer types in C (or static_casting in C++). The conversion between the two Swift types (the two variants of UnsafePointer) is safe, but of course they are still UnsafePointers, so you must be certain you're accessing the memory correctly; you are still responsible for allocation and deallocation.
I would like to declare an array of pointer with an initialization
Apb : array [0..2] of pointer to bool := adr(r0), adr(r1), adr(r2);
Where r0, r1, r2 are declared in Modbus like Bitwise holding register.
I got an error: Wrong initial value.
In case:
Apb : array [0..2] of pointer to bool;
Apb[0]^ := r0;
Everything works as I want.
I think that POU variable declarations do not want function calls in them or even variables assigned to other variables.
The only way to have variables in your declaration is to use VAR_CONSTANTs. You will still have to do some legwork, but it can make larger-scale substitutions easier to manage.
There is also a way to use dynamic values using pragmas (I never really use pragmas although, so Im not certain of how powerful it is).
Coming from more standard programming languages, this one has similar rules and constructs as C, but not nearly as much flexibility, dreadful syntax, and nothing even resembling 'void' types. I ended up using python templates to help generate POU variable declaration headers because the allowed syntax is quite strict, leading to excessively verbose declarations.
Variables of struct declared by data type of language in the header file. Usually data type using to declare variables, but other data type pass to preprocessors. When we should use to a data type send to preprocessor for declare variables? Why data type and variables send to processor?
#define DECLARE_REFERENCE(type, name) \
union { type name; int64_t name##_; }
typedef struct _STRING
{
int32_t flags;
int32_t length;
DECLARE_REFERENCE(char*, identifier);
DECLARE_REFERENCE(uint8_t*, string);
DECLARE_REFERENCE(uint8_t*, mask);
DECLARE_REFERENCE(MATCH*, matches_list_head);
DECLARE_REFERENCE(MATCH*, matches_list_tail);
REGEXP re;
} STRING;
Why this code is doing this for declarations? Because as the body of DECLARE_REFERENCE shows, when a type and name are passed to this macro it does more than just the declaration - it builds something else out of the name as well, for some other unknown purpose. If you only wanted to declare a variable, you wouldn't do this - it does something distinct from simply declaring one variable.
What it actually does? The unions that the macro declares provide a second name for accessing the same space as a different type. In this case you can get at the references themselves, or also at an unconverted integer representation of their bit pattern. Assuming that int64_t is the same size as a pointer on the target, anyway.
Using a macro for this potentially serves several purposes I can think of off the bat:
Saves keystrokes
Makes the code more readable - but only to people who already know what the macros mean
If the secondary way of getting at reference data is only used for debugging purposes, it can be disabled easily for a release build, generating compiler errors on any surviving debug code
It enforces the secondary status of the access path, hiding it from people who just want to see what's contained in the struct and its formal interface
Should you do this? No. This does more than just declare variables, it also does something else, and that other thing is clearly specific to the gory internals of the rest of the containing program. Without seeing the rest of the program we may never fully understand the rest of what it does.
When you need to do something specific to the internals of your program, you'll (hopefully) know when it's time to invent your own thing-like-this (most likely never); but don't copy others.
So the overall lesson here is to identify places where people aren't writing in straightforward C, but are coding to their particular application, and to separate those two, and not take quirks from a specific program as guidelines for the language as a whole.
Sometimes it is necessary to have a number of declarations which are guaranteed to have some relationship to each other. Some simple kinds of relationships such as constants that need to be numbered consecutively can be handled using enum declarations, but some applications require more complex relationships that the compiler can't handle directly. For example, one might wish to have a set of enum values and a set of string literals and ensure that they remain in sync with each other. If one declares something like:
#define GENERATE_STATE_ENUM_LIST \
ENUM_LIST_ITEM(STATE_DEFAULT, "Default") \
ENUM_LIST_ITEM(STATE_INIT, "Initializing") \
ENUM_LIST_ITEM(STATE_READY, "Ready") \
ENUM_LIST_ITEM(STATE_SLEEPING, "Sleeping") \
ENUM_LIST_ITEM(STATE_REQ_SYNC, "Starting synchronization") \
// This line should be left blank except for this comment
Then code can use the GENERATE_STATE_ENUM_LIST macro both to declare an enum type and a string array, and ensure that even if items are added or removed from the list each string will match up with its proper enum value. By contrast, if the array and enum declarations were separate, adding a new state to one but not the other could cause the values to get "out of sync".
I'm not sure what the purpose the macros in your particular case, but the pattern can sometimes be a reasonable one. The biggest 'question' is whether it's better to (ab)use the C preprocessor so as to allow such relationships to be expressed in valid-but-ugly C code, or whether it would be better to use some other tool to take a list of states and would generate the appropriate C code from that.
In my constant file, I have included the below line
NSString * ALERT_OK = NSLocalizedString(#"Ok",#"Ok");
After this, when I tried to compile I am receiving the below error
Initialiser element is not a compile time constant
How can I debug this?
The problem is that NSLocalizedString is a function which returns different values, depending on the language. It is not a constant which can be figured out until the system is running.
Instead, use:
#define ALERT_OK NSLocalizedString(#"Ok",#"Ok");
And it will now simply replace ALERT_OK with the function and you will be fine. (Note that you should be using some kind of prefix to all global values like this so that you don't accidentally create something with the same name being used somewhere else.)
Which of these two definitions is correct?
Statically typed - Type matching is checked at compile time (and therefore can only be applied to compiled languages)
Dynamically typed - Type matching is checked at run time, or not at all. (this term can be applied to compiled or interpreted languages)
Statically typed - Types are assigned to variables, so that I would say 'x is of type int'.
Dynamically typed - types are assigned to values (if at all), so that I would say 'x is holding an int'
By this definition, static or dynamic typing is not tied to compiled or interpreted languages.
Which is correct, or is neither one quite right?
Which is correct, or is neither one quite right?
The first pair of definitions are closer but not quite right.
Statically typed - Type matching is checked at compile time (and therefore can only be applied to compiled languages)
This is tricky. I think if a language were interpreted but did type checking before execution began then it would still be statically typed. The OCaml REPL is almost an example of this except it technically compiles (and type checks) source code into its own byte code and then interprets the byte code.
Dynamically typed - Type matching is checked at run time, or not at all.
Rather:
Dynamically typed - Type checking is done at run time.
Untyped - Type checking is not done.
Statically typed - Types are assigned to variables, so that I would say 'x is of type int'.
Dynamically typed - types are assigned to values (if at all), so that I would say 'x is holding an int'
Variables are irrelevant. Although you only see types explicitly in the source code of many statically typed languages at variable and function definitions all of the subexpressions also have static types. For example, "foo" + 3 is usually a static type error because you cannot add a string to an int but there is no variable involved.
One helpful way to look at the word static is this: static properties are those that hold for all possible executions of the program on all possible inputs. Then you can look at any given language or type system and consider which static properties can it verify, for example:
JavaScript: no segfaults/memory errors
Java/C#/F#: if a program compiled and a variable had a type T, then the variable only holds values of this type - in all executions. But, sadly, reference types also admit null as a value - the billion dollar mistake.
ML has no null, making the above guarantee stronger
Haskell can verify statements about side effects, for example a property such as "this program does not print anything on stdout"
Coq also verifies termination - "this program terminates on all inputs"
How much do you want to verify, this depends on taste and the problem at hand. All magic (verification) comes at price.
If you have never ever seen ML before, do give it a try. At least give 5 minutes of attention to Yaron Minsky's talk. It can change your life as a programmer.
The second is a better definition in my eyes, assuming you're not looking for an explanation as to why or how things work.
Better again would be to say that
Static typing gives variables an EXPLICIT type that CANNOT change
Dynamic typing gives variables an IMPLICIT type that CAN change
I like the latter definition. Consider the type checking when casting from a base class to a derived class in object oriented languages like Java or C++ which fits the second definition and not the first. It's a compiled language with (optional) dynamic type checking.