Whitespace and parentheses in pointer declarations in Objective-C - objective-c

I understand from earlier questions that whitespace is irrelevant in pointer declarations in Objective-C, e.g:
float* powerPtr;
float * powerPtr;
float *powerPtr;
do mean exactly the same (apart from stylistic considerations...) but is
(float *)powerPtr;
(with parentheses) the same too? Don't these parentheses implicitly "mean" that the asterisk should be in some way related to float, when it should be instead more logically related to powerPtr? (The actual pointer is actually powerPtr, not float, if I am right)

Your code:
(float *)powerPtr;
is not a valid declaration in (Objective-)C.
This is an expression which casts the value in the variable powerPtr to be of type float *.
The result of that cast is just discarded as it is not used, your compiler might give a warning - Xcode 8 issues an "Expression result unused".
Addendum
From your comment the syntax you show was meant to be part of a method declaration, e.g. something like:
- (void)doSomething:(float *)powerPtr;
that would occur in an #interface. The parentheses here are not being used for grouping per se but to delimit the type. As to you concern:
Don't these parentheses implicitly "mean" that the asterisk should be in some way related to float, when it should be instead more logically related to powerPtr?
The * is part of the type, float * is the type specification for "pointer to float". The identifier powerPtr is associated with the whole type specification.
HTH

Related

Kotlin: At which situations does implicit conversion happen?

I am a beginner in Kotlin.
I'm most familiar with Python, and I just read through the basic Java Tutorial https://docs.oracle.com/javase/tutorial/java/index.html before jumping into Kotlin.
A question came up in my mind while reading this section of the documentation of Kotlin
https://kotlinlang.org/docs/reference/basic-types.html#explicit-conversions
What I have understood from above section of the documentation is:
For assignments =, implicit type conversion happens. If the lefthand side's type is a supertype or same type of righthand side's type the code would compile. Otherwise it's a compile error. In case of Int and Long, they are both subtypes of Number but neither of them subtypes of each other, so the implicit conversion would not work. Therefore we need to use methods like .toLong() or .toInt() to explicitly convert them.
Then when I read the part
val l = 1L + 3 // Long + Int => Long
I started wondering if implicit type conversion would be taking place in this situation.
The documentation says this has to do with the operator overloading.
How is this operator overloading implemented under the hood?
I tried to find the source code at Github https://github.com/JetBrains/kotlin/blob/master/core/builtins/native/kotlin/Primitives.kt ,
but here the functions are only declared but not implemented. Where can I find the implementations?
It seems that operation overloading does not actually perform type conversion. Do we just implementing all possible functions with same name but different parameter type signatures, so that the type is inferred, then the function with the matching signature is selected?
And the general question: In Kotlin, exactly at which situations does implicit conversion happen?
For assignments =, implicit type conversion happens. If the lefthand side's type is a supertype or same type of righthand side's type the code would compile.
Assignments aren't special in this. More generally, if the expected type of an expression is a supertype or the same as actual type, the code compiles; it's just that the expected type for the right-hand side of an assignment is the left-hand side's type. I wouldn't say there is an implicit conversion inserted, but I don't think anything breaks if you see it that way.
Do we just implementing all possible functions with same name but different parameter type signatures, so that the type is inferred, then the function with the matching signature is selected?
Yes, exactly (for this case). If you want to support primitive types, you need to provide overloads for all of them.
So 1L + 3 is just a method call so far as the parsing and type-checking is concerned (`Long.plus(Int): Long specifically), no implicit conversion is involved. But these methods are built into the compiler to handle specially which is why you don't see an implementation.
It becomes two bytecode instructions i2l ("convert an int into a long") and ladd ("add two longs"), but that's not something you should probably care about yet, or for a long time.
And the general question: In Kotlin, exactly at which situations does implicit conversion happen?
Smart casts are the closest Kotlin has to implicit conversions but they are sufficiently different from i.c.s in other languages that I wouldn't use the name. So I'd say never.

What is ${type}Var in Kotlin/Native?

This documentation is very unclear for me when it tries to say what is ${type}Var.
...for Kotlin enums it is named ${type}Var
wat?! What is Kotlin enums? Regular Kotlin enums?
enum class MyEnum {
FIRST, SECOND
}
I don't think it implied.
Okay, Let's look at the examples in this documentation:
struct S* is mapped to CPointer<S> , int8_t* is mapped to CPointer<int_8tVar>
Okay, it's clear
char** is mapped to CPointer<CPointerVar<ByteVar>>
Why is char** mapped to CPointer<CPointerVar<ByteVar>> but not to CPointer<CPointer<Byte>>?
So finally the question is: what is IntVar, LongVar, CPointerVar<T> and other things like ${type}Var?
You should read the whole paragraph again carefully.
All the supported C types have corresponding representations in Kotlin:
Enums can be mapped to Kotlin enum
Also in C there are lvalues and rvalues (In C++ the equivivalent is Type & for lvalues and Type for rvalues). The main distinguish is that lvalues can be set to some value, while rvalues can't be changed after the initialization. So for each type in C you need it's own Kotlin type for lvalue and for rvalue.
In the topic
All the supported C types have corresponding representations in Kotlin:
only rvalues are considered.
But for lvalues the only thing you need to add is Var to end of type. The only exception is
For structs (and typedefs to structs) this representation is the main one and has the same name as the struct itself
Now let's return to enums. The regular Kotlin enums are mapped to the regular C enums. So actually FIRST and SECOND have type MyEnum in both languages. But what if you want to create a variable containing MyEnum for example:
// This is C Code
MyEnum a = FIRST;
a has type MyEnum in C, but it's lvalue (in C++ that's MyEnum &), so in Kotlin a will have type MyEnumVar because that's exactly what is said in documentation: ${type}Var, where ${type} = MyEnum.
To the next questions:
The type argument T of CPointer must be one of the "lvalue" types
So for struct S* it should be CPointer<SVar>, but remember that structs are exceptions and we shouldn't add Var, so that's just CPointer<S>.
int8_t* is CPointer<int_8tVar> - no exception here.
char* is CPointer<ByteVar> - again no exception (only lvalue types, except for structs).
char** is CPointer<CPointerVar<ByteVar>> as we need lvalue for CPointer<ByteVar> and that's exactly CPointerVar<ByteVar>.
Finally:
IntVar, LongVar, CPointerVar<T> and other things are lvalues of types int, long, CPointer. That may be needed if you want to change the object in the function. Something like Ref<${type}> in Java.
what is IntVar, LongVar, CPointerVar<T> and other things like ${type}Var?
That's in the beginning of the sentence the end of which you quoted:
the Kotlin type representing the lvalue of this type, i.e., the value located in memory rather than a simple immutable self-contained value
"located in memory" means that you can take their address (using & operator in C, or .ptr in Kotlin).
wat?! What is Kotlin enums? Regular Kotlin enums?
Yes, so when Kotlin/Native sees MyEnum, it also generates MyEnumVar.
Why is char** mapped to CPointer<CPointerVar<ByteVar>> but not to CPointer<CPointer<Byte>>?
CPointer<CPointer<Byte>> is illegal: CPointer's type parameter must extend CPointed, and Byte and CPointer<T> don't. And the reason they need to extend CPointed is because dereferencing a pointer gives an lvalue: something that has an address!
See https://learn.microsoft.com/en-us/cpp/c-language/l-value-and-r-value-expressions or https://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c/ for more about lvalues in C (and C++).

How one deals with multiple pointer level (like char**) in Squeak FFI

I want to deal with a structure like this struct foo {char *name; char **fields ; size_t nfields};
If I define corresponding structure in Squeak
ExternalStructure subclass: #Foo
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'FFI-Tests'.
and define the fields naively with
Foo class>fields
^#(
(name 'char*')
(fields 'char**')
(nfields 'unsigned long')
)
then generate the accessors with Foo defineFields, I get those undifferentiated types for name and fields:
Foo>>name
^ExternalData fromHandle: (handle pointerAt: 1) type: ExternalType char asPointerType
Foo>>fields
^ExternalData fromHandle: (handle pointerAt: 5) type: ExternalType char asPointerType
That is troubling, the second indirection is missing for the fields accessor.
How should I specify fields accessor in the spec?
If not possible, how do I define it manually?
And I have the same problem for this HDF5 function prototype: int H5Tget_array_dims(hid_t tid, hsize_t *dims[])
The following syntax is not accepted:
H5Tget_array_dims: tid with: dims
<cdecl: long 'H5Tget_array_dims'(Hid_t Hsize_t * * )>
The compiler barks argument expected -> before the second *...
I add to resort to void * instead, that is totally bypassing typechecking - less than ideal...
Any idea how to deal correctly with such prototype?
Since Compiler-mt.435, the parser will not complain anymore but call back to ExternalType>>asPointerToPointerType. See source.squeak.org/trunk/Compiler-mt.435.diff and source.squeak.org/FFI/FFI-Kernel-mt.96.diff
At the time of writing this, such pointer-to-pointer type will be treated as regular pointer type. So, you loose the information that the external type actually points to an array of pointers.
When would one need that information?
When coercing arguments in the FFI plugin during the call
When constructing the returned object in the FFI plugin during the call
When interpreting instances of ExternalData from struct fields and FFI call return values
In tools such as the object explorer
There already several kinds of RawBitsArray in Squeak. Adding String and ExternalStructure (incl. packed or union) to the mix, we have all kinds of objects in Squeak to map the inner-most dimension (i.e., int*, char*, void*). ExternalData can represent the other levels of the multi-dimensional array (i.e., int**, char**, void** and so on).
So, there are remaining tasks here:
Store that pointer dimension information maybe in a new external type to be found via ExternalType>>referencedType. We may want to put new information into compiledSpec. See http://forum.world.st/FFI-Plugin-Question-about-multi-dimensional-arrays-e-g-char-int-void-td5118484.html
Update value reading in ExternalArray to unwrap one pointer after the other; and let the code generator for struct-field accessors generate code in a similar fashion.
Extend argument coercing in the plugin to accept arrays of the already supported arrays (i.e. String etc.)

Exclamation operator?

I'm learning D and have seen a lot of code like this:
ushort x = to!ushort(args[1]);
I assume this casts args[1] to ushort, but what's the difference between this and cast(ushort)?
EDIT: And what other uses does the exclamation mark operator have?
In D,
to!ushort(args[1])
is shorthand for the template instantiation
to!(ushort)(args[1])
and is similar to
to<ushort>(args[1])
in languages like C++/Java/C#.
The exclamation point is to note the fact that it's not a regular argument, but a template argument.
The notation does not use angle brackets because those are ridiculously difficult to parse correctly for a compiler (they make the grammar very context-sensitive), which makes it that much more difficult to implement a correct compiler. See here for more info.
The only other use I know about is just the unary 'not' operation (e.g. false == !true)... I can't think of any other uses at the moment.
Regarding the cast:
cast(ushort) is an unchecked cast, so it won't throw an exception if the value is out of range.
to!ushort() is a checked cast, so it throws an exception if the value is out of range.
The exclamation mark here is not an operator, it is just a token part of the explicit template instantiation syntax (described in detail here).
std.conv.to (docs) is a function template for converting between arbitrary types. It is implemented entirely in the library and has no special support in the language. It has a broader and different scope compared to the cast operator.
The to template takes two type parameters; a "to" type and a "from" type, in that order. In your example, the template is explicitly instantiated with the single type argument ushort for the "to" parameter, and a second type argument string (assuming args comes from the first parameter to main) is automatically inferred from the regular function argument passed to the function (args[1]) as the "from" parameter.
The resulting function takes a string parameter and returns a ushort parsed from that string, or throws an exception if it failed. The cast operator will not attempt this kind of high-level conversion.
Note that if there is more than one explicit template parameter, or that parameter has more than one token in it (ushort is a single keyword token), you must wrap the template parameter list in parentheses:
ushort result;
result = to!(typeof(result))(args[1]);
In this example, typeof, (, result and ) are four separate tokens and the parentheses are thus required.
To answer your last question, the ! token is also used for the unary not operator, unrelated to template instantiations:
bool yes = true;
bool no = !yes; // 'no' is false
You already got two excellent answers by jA_cOp and Merhdad. I just want answer directly to the OP question (what's the difference between this and cast(ushort)?) - The difference is that cast(ushort)args[1] will not work (you cannot cast from a string to an uint just like that), while the to!(type)(param) template knows what to do with the string and how to convert it to the primitive type.

Passing integers when floats are called for

If the arguments of a method call for floats to be passed, can one simply pass 10 as opposed to 10.0? I have been doing this, but often see code which specify .0 and have been wondering if there are any reasons to do so. Thank you.
It's not necessary, but it's a good idea to use the correct type and/or add explicit casts when you do this - more for self-documentation purposes than anything else. For literal values just specify the constant as e.g. 10.0f - for variables just use a C-style typecast, e.g. (float)i.
The compiler will generally coerce numbers to the correct type, but it doesn't hurt to be explicit to promote readability.
The constant value 10.0 is actually a double to most C and C++ compilers, whereas 10.0f is a single-precision floating point number. If you're passing a variable to a function and you know the passed type is wrong, cast it using C notation (float)i or C++ notation float(i) depending on your compiler.