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"};
Related
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.
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.
If I have 2D queue of ints, I would expect to be able to declare it inline like so:
int my_queue[$][$] = {{1, 2}, {3, 4}};
I have also seen
typedef int int_queue[$];
int_queue my_queue[$] = {{1, 2}, {3, 4}};
Instead, when I compile, VCS provides me with an Incompatible Complex Type error:
Type of source expression is incompatible with type of target expression.
Mismatching types cannot be used in assignments, initializations and
instantiations. The type of the target is 'int$[$][$]', while the type of
the source is 'bit[63:0]'.
Which implies to me that VCS expects the right hand side of the equation to be cast properly. The way around this that I have been using is:
typedef int int_queue[$];
typedef int_queue int_queue_of_queues[$];
int_queue_of_queues my_queue = int_queue_of_queues'{{1, 2}, {3, 4}};
But this adds N extra typedefs and lines for N dimensions, and I would rather do this in one line. If I had a way to cast the right hand side of the declaration without a typedef, then this would be simple, but I don't know if that is possible.
The array concatenation syntax only works on a single dimension. You cannot nest the {}'s because of cases where there is ambiguity between array {} and integral {} concatenation. You need to use array assignment pattern in the outer, or both dimensions. I prefer using assignment patterns for both dimensions making it clearer that these are array elements, not integral concatenations.
int my_queue[$][$] = '{'{1, 2}, '{3, 4}};
See section 10.10 Unpacked array concatenation in the IEEE 1800-2017
LRM.
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 does one pass a Simulink.Parameter structure (which, in my case, is a structure of structures) to a C S-function?
Edit:
Information on Simulink.Parameter
You can create a Simulink.Parameter object this way:
modelParameters = Simulink.Parameter;
modelParameters.Value = myStruct;
modelParameters.CoderInfo.StorageClass = 'ExportedGlobal';
The myStruct value is a regular matlab structure of structures. This is how it looks in my case:
This is a special object type for passing parameters to Simulink and I am looking for a mechanism to access it from a C S-function.
Download a MnWE from here.
Edit 2:
I read the parameters this way:
modelParameters_T *modelParameters = (modelParameters_T*)mxGetPr(ssGetSFcnParam(S, PARAM_STRUCT));
But I can see why this approach doesn't work - the structure object from Matlab is not similar to a C structure, i.e. is not contiguous in memory and contains other properties too. I think I will cast the Matlab structure to an array and then cast the array in C to my struct definition.
mxGetPr is not the right way to access your parameter which is an object type. It is not a struct type. Even if it is a struct type you need to use mxArray API to access struct fields. You need to use something like the following code to access the fields.
mxArray* param = ssGetSFcnParam(S, PARAM_STRUCT);
mxArray* prop = mxGetProperty(param, 0, "Value"); // Get Value property from param object
// If prop is double precision use the following line to get its value
double* prop = *(mxGetPr(prop));
Check out mxArray API in the doc for accessing different types of mxArrays.