Swift array address is not same as &array[0] - swift

Document said:
An in-out expression that contains a mutable variable, property, or subscript reference of type Type, which is passed as a pointer to the address of the left-hand side identifier.
A [Type] value, which is passed as a pointer to the start of the array.
But when I run the following code :
func print<Type>(unsafePointer pointer: UnsafePointer<Type>) {
print("\(pointer) ==> \(pointer.pointee) : \(Type.self)")
}
var array = [1, 2, 3, 4]
print(unsafePointer: array)
print(unsafePointer: &array[0])
I get
0x0000000104204240 ==> 1 : Int
0x00007ffeefbff440 ==> 1 : Int
Why their addresses are different?

Here
print(unsafePointer: array)
a pointer to the first element of the array storage is passed to the function. And here
print(unsafePointer: &array[0])
the subscript operator is called on the array (returning an Int) and the address of that (temporary) integer is passed to the function, not the address where the original array element is stored.
That becomes more obvious if you call the functions twice:
var array = [1, 2, 3, 4]
print(unsafePointer: array) // 0x00007ffeefbff2e0
print(unsafePointer: array) // 0x00007ffeefbff2e0, same as previous address
print(unsafePointer: &array[0]) // 0x00007ffeefbff320
print(unsafePointer: &array[0]) // 0x00007ffeefbff340, different from previous address
In addition, passing an in-out expression to a function can make a temporary copy, see for example Swift: always copies on inout?.

Arrays in Swift have value semantics, not the reference semantics of arrays in C or Objective-C. The reason you're seeing different addresses (and addresses at all) is that every time you pass the array as a parameter, you're actually telling Swift to bridge your Array struct to an instance of NSArray.

Related

Why can I pass [UInt8] type to the UnsafePointer<UInt8> type parameter?

We all know that [UInt8] type is not equal UnsafePointer<UInt8>,
But why can I pass [UInt8] type to UnsafePointer<UInt8> type parameter:
let p = UnsafeMutablePointer<UInt8>.allocate(capacity: 4)
p.initialize(repeating: 0, count: 4)
let ary:[UInt8] = [1,2,3,4]
p.assign(from: ary, count: 4) // It's OK, why?
As shown aboveļ¼Œp.assign method frist parameter type is UnsafePointer<T>, but It's OK when I pass the type [UInt8]...
Why is that? Thanks! ;)
It's just a shortcut.
An unsafe pointer is effectively a C array: what we are pointing at is the first address of a contiguous block of memory. Therefore Swift gives you some nice help for when you have a Swift array from which you want to write to the memory: this Swift array is nothing whatever like a C array, but nevertheless, you can pass a pointer to the Swift array or even the Swift array itself, including an array literal, and Swift will just do the right thing.

Why result of reversed() does behave itself like being an Array? [duplicate]

I'm wondering about the reversed() method on a swift Array:
var items = ["a", "b", "c"]
items = items.reversed()
the signature of the reversed method from the Apple doc says that it returns a
ReversedRandomAccessCollection<Array<Element>>
could that be assigned back to items without doing what the apple doc say which is
For example, to get the reversed version of an array, initialize a new Array instance from the result of this reversed() method.
or would it give problem in the future? (since the compiler doesn't complain)
There are 3 overloads of reversed() for an Array in Swift 3:
Treating the Array as a RandomAccessCollection,func reversed() -> ReversedRandomAccessCollection<Self> (O(1))
Treating the Array as a BidirectionalCollection,func reversed() -> ReversedCollection<Self> (O(1))
Treating the Array as a Sequence,func reversed() -> [Self.Iterator.Element] (O(n))
By default, reversed() pick the RandomAccessCollection's overload and return a ReversedRandomAccessCollection. However, when you write
items = items.reversed()
you are forcing the RHS to return a type convertible to the LHS ([String]). Thus, only the 3rd overload that returns an array will be chosen.
That overload will copy the whole sequence (thus O(n)), so there is no problem overwriting the original array.
Instead of items = items.reversed(), which creates a copy of the array, reverse that and copy it back, you could reach the same effect using the mutating function items.reverse(), which does the reversion in-place without copying the array twice.

Can't mutate [Int] using .remove(at:)

var bigNum = [2,34,5].remove(at: 2)
Error:
Playground execution failed: error: CalculatorPlayGround.playground:35:14: error: cannot use mutating member on immutable value of type '[Int]'
var bigNum = [2,34,5].remove(at: 2)
But
var bigNum = [2,34,5]
var b = bigNum.remove(at: 2)
is ok.
What is the difference? Why does it work in the second case?
.remove(at:) tries to mutate the array you call it on.
When you create the array like you did in your first example ([1,2,3].whatever), it creates an immutable constant, as if you were to create it like this:
let array = [2, 34, 5] //not mutable
If you force it to create the array as a variable, it is mutable:
var array = [2, 34, 5] //mutable
Note
I don't know exactly what you are trying to do, but bigNum makes me assume you're trying to get a number from the array? Because right now, bigNum would become this array: [2, 34] instead of just a number.
[2,34,5] in itself is a literal, and as such is immutable in Swift (i.e. you can't write [2,34,5].remove(at: 2)). To apply a mutating function, you first need to store your array in a mutable container, using the var keyword:
var bigNum = [2,34,5]
Only after doing so, you can use mutating func .remove(at:) on mutable bigNum.

How to assign an array to struct member array?

How to assign c type array to struct member that is also an array of the same type? Here's my struct:
typedef struct {
uint8_t type;
uint8_t data[10];
} MyStruct;
Here's the creation of the struct:
MyStruct myStruct;
Here's generation of some array:
uint8_t generatedArray[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Here's my assignment:
myStruct.data = generatedArray;
As other answers have stated an array is not directly assignable and you must use a function such as memcpy:
memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));
However...
C is a language with a long history. Early languages had roughly the notion of "little" and "large" types, the former being directly assignable and the latter not. Some later languages made everything assignable (or for functional languages, values).
Original C had primitive types; integer, float, etc.; and arrays of these types. The former, being "little", were assignable, the latter, being "large", were not. Subsequently C gained structures, and decided these were "little"...
So, a little strangely, while you cannot directly assign one array to another you can assign on structure to another, and in particular you can assign a structure with just one field which is an array... You can also write literal structure values, including for those with array-valued fields; and being C with its "types are comments" approach you can cast a pointer to an array to a pointer to a structure...
The above means you can write "fun" code like:
typedef struct
{
uint8_t type;
uint8_t data[10];
} MyStruct;
typedef struct
{
uint8_t data[10];
} MyArray;
typedef struct
{
uint8_t type;
MyArray array;
} MyStruct2;
void arrayAssignment(int x)
{
MyStruct myStruct;
MyArray generatedArray = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; // structure literal
*(MyArray *)&myStruct.data = generatedArray;
uint8_t generatedArray2[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; // array literal
*(MyArray *)&myStruct.data = *(MyArray *)generatedArray2;
MyStruct2 myStruct2;
myStruct2.array = generatedArray; // no casts at all, but element access is myStruct2.array.data[index]
}
Note that none of the casts, indirections, etc. or in the final example the extra array. in the indexing cost anything in the compiled code - they are all simply ways to persuade the compiler to use its built-in array assignment.
Many would of course argue against regular uses of these techniques!
Arrays cannot be assigned to each other, that is, an array identifier is not allowed to be on the left side of an assignment. When on the right side, the array is said to decay to a pointer to its first element, so it doesn't really represent the whole chunk.
You should use memcpy instead, and pass the size of the array which can be obtained via the sizeof operator. For short arrays, an optimizing compiler may be able to substitute the memcpy call with more efficient instructions to exploit the target architecture better.
You are attempting to assign to an array, but an array cannot be assigned to. An array is, however, an lvalue:
The following object types are lvalues, but not modifiable lvalues:
An array type
An incomplete type
A const-qualified type
An object is a structure or union type and one of its members has a const-qualified type
You'll need to use memcpy instead. You ought to pass sizeof(myStruct.data) as the third argument to memcpy:
memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));
You can't directly assign an array like that. You'll have to copy it over.
I wonder how your compiler let you do that assignment. You cannot use array as modifiable lvalue. Also when used as rvalue an array represents a pointer to the first element in the array.
Other ways of achieving this would be to use pointers or to use memcopy()
With C99 you can use compound literals and string literals as initializer ( if uint8_t has the same bit-representation as char )
MyStruct myStruct={.data="\1\2\3\4\5\6\7\x8\x9\xa"};
...
MyStruct myStruct;
myStruct = (MyStruct){.data="\1\2\3\4\5\6\7\x8\x9\xa"};

What does Array as Object mean in Basic4Android?

SQL1.ExecNonQuery2("INSERT INTO table1 VALUES(?,?,?)",Array As Object("def",3,4))
I don't seem to understand why the argument list in the above statement is declared in the form of Array as Object('xx','xx''xx').How is it exactly being converted into a list parameter ?
Array As xxx is a shorthand syntax for declaring a new array and assigning the values.
Array As Object("def", 3, 4)
Is equivalent to:
Dim arr As Object(3)
arr(0) = "def" : arr(1) = 3 : arr(1) = 4
Basic4android automatically wraps arrays as lists when needed. The items are not copied, it is the whole array that is wrapped in a list. Therefore the above code is valid as it creates an array which is then wrapped as a List.