(disclaimer: just ignore mat_constr function because it's not related to this question (it's mat_constructor of another question I've posted, because I'm trying to edit the mat_transpose function on my own)).
this is a very simple exercise, yet I can't figure out how to define an array (correctly).
I have a
struct matrix {
size_t rows;
size_t cols;
double* data
};
in the main function, I have to define a variable of type "struct matrix", and then I have to define the array. As follows:
int main(void) {
struct matrix A;
mat_constr(&A, 4, 4);
A.data = { /* a number */, /* another number* /, /* etc. */ };
}
the problem is that the compiler highlighted the first "{". in the array definition, and it says: "expected an expression".
this is strange, because this is the definition style of the array, am I wrong?
Assuming that mat_constr allocates memory as a single array of double, and makes the data member point to it, then you can copy to this array.
For example using memcpy and compound literals:
memcpy(A.data, (double[16]){ 1, 2, 3, ... }, 16 * sizeof(double));
[I made an assumption that mat_constr allocates a single array of 4 * 4 elements in my example above. Please don't let us make assumptions, create a proper Minimal, Reproducible Example instead.]
You can of course copy a value to each element of the array individually instead:
A.data[0] = 1;
A.data[1] = 2;
A.data[2] = 3;
...
And if you want to set all elements to a single value you can of course use a loop:
for (unsigned i = 0; i < 16; ++i)
{
A.data[i] = 5;
}
Or if you want to set all elements to zero then either allocate with calloc:
A->data = calloc(A->rows * A->cols, sizeof(double));
Or use memset:
memset(A.data, 0, 16 * sizeof(double));
The problem is that C has no notion of array litteral. And the equal sign can be used for 2 very different operations, assignment and initialization.
The brace enclosed expression can be used to initialize an array, but cannot be used to initialize a pointer nor can it be assigned to a pointer:
double data[] = {1., 2., 3.}; // array initialization: valid
double *data = {1., 2., 3.}; // INVALID attempt to initialize a pointer
double *d2;
d2 = {1., 2., 3.}; // INVALID assignment to a pointer
Related
I want to understand how the pointer to the structure is passed to the function argument and implemented. How is avrg_stpc[idx_u16].sum_f32 array is working?
typedef struct
{
const float * input_f32p;
float avg_f32;
float sum_f32;
float factor_f32;
unsigned int rs_u16;
} avgminmax_avg_t;
void avgminmax_AvgCalculate_vd(
avgminmax_avg_t * const avrg_stpc,
const unsigned int numOfEntrys_u16c)
{
unsigned int idx_u16 = 0u;
do
{
avrg_stpc[idx_u16].sum_f32 += (*avrg_stpc[idx_u16].input_f32p
- avrg_stpc[idx_u16].avg_f32);
avrg_stpc[idx_u16].avg_f32 = (avrg_stpc[idx_u16].sum_f32 *
avrg_stpc[idx_u16].factor_f32);
idx_u16++;
}while(idx_u16 < numOfEntrys_u16c);
}
A few points that could help you understand arrays and pointers and their relationship:
A pointer really only points to one "object", but that object might be the first in an array.
Arrays naturally decays to pointers to their first element.
And array indexing is equivalent to pointers arithmetic (for any pointer or array a and index i, the expression a[i] is exactly equal to *(a + i)).
As for your specific example code, perhaps it would be easier if you thought of it similar to this:
avgminmax_avg_t *temp_ptr = &avrg_stpc[idx_u16];
temp_ptr->sum_f32 += ...;
temp_ptr->avg_f32 = ...;
Or perhaps like:
avgminmax_avg_t temp_object = avrg_stpc[idx_u16];
temp_object.sum_f32 += ...;
temp_object.avg_f32 = ...;
avrg_stpc[idx_u16] = temp_obj;
Both the snippets above will lead to the same result as your existing code, but requires an extra temporary variable, and in the latter snippet copying of the structure twice.
avrg_stpc is regarded as an array (possibly, allocated on heap via .*alloc); since its bounds can't be known, hence the second argument to the function. See here: https://en.cppreference.com/w/c/language/operator_member_access
Suppose I have a double array double myArray[16] with 16 elements. I want to perform a function on each subset of four elements, i.e. the first subset is myArray[0], myArray[1], myArray[2], myArray[3], the second is myArray[4], myArray[5], myArray[6], myArray[7], and so on.
I want to pass the subset arrays using a pointer to a void function that operates on the subset only and write the values to the addresses passed to the function. If I wanted to use all the elements beginning with myArray[8], I could pass &myArray[8] to the function, but I need to pass only a predetermined length (4 in this example).
Any help is appreciated!
To allow the function to know the length of a passed array, the array needs to carry this information in a separate piece of memory. That is an overhead, and C is designed for zero overhead, so it does not support this.
There are languages that automatically deliver this information (and as a consequence, they are slower).
Your only options are to either hard-code the size of array you want to work with in the function (which could be ok or a very bed idea, depending on your context), or pass it as an additional parameter.
Do you want to use an array[16] as if it was an array[4][4]?
You can use an union:
#include <stdio.h>
union set {
double arr[16];
double sub[4][4];
};
static void func(void *data) /* Why not double *? */
{
double *x = data;
int i;
for (i = 0; i < 4; i++) {
printf("%f\n", *x++);
}
}
int main(void)
{
union set x = {.arr = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.}};
int i;
for (i = 0; i < 4; i++) {
func(&x.sub[i]);
}
return 0;
}
need to pass only a predetermined length
In C, arrays are continuous. To operate on elements 0,1,2,3, the function need only receive the address of element 0. To operate on elements 8,9,10,11, the function need only receive the address of element 8. So code does not pass a length of the array, but the address of the base of the subset of the array.
#define N 16
#define DELTA 4
void fun(int base, double *a) {
for (int i=0; i<N; i++) {
printf("%2d %e\n", base + i, a[i]);
}
}
double myArray[N];
assert(N%DELTA == 0);
for (int i=0 i<N; i += DELTA) {
fun(i, &myArray[i]);
}
Even if you have a function void myFunction(double arr[4]), the C compiler treats this exactly like `void myFunctoin(double *arr). The array itself is not being passed by value; only a pointer value is passed in, and the array elements are referenced using pointer arithmetic and dereferencing.
In C there's almost no difference between a pointer an an array. You can't assign to an array, but you can assign to a pointer. Aside from that they're nearly interchangeable.
int array[10];
int *ptr = &array[0];
// All 4 of these do the same thing
array[3] = 5;
*(array + 3) = 5;
ptr[3] = 5;
*(ptr + 3) = 5;
// all 4 of these do the same thing too
functionCall(&array[3]);
functionCall(array + 3);
functionCall(&ptr[3]);
functionCall(ptr + 3);
// this is pretty much the only thing different
printf("sizeof(array)=%d\n", sizeof(array)); // prints sizeof(int)*10
printf("sizeof(ptr)=%d\n", sizeof(ptr)); // prints sizeof(int *)
// and this
ptr = array + 5; // fine
array = array + 5; // will not compile, since you can't assign to arrays.
In C you need to set the size of the array at compile time. It really doesn't like when you dynamically change the length of an array. You should get an exception when compiling the program. For this case you would use a pointer that pointed to a contiguous space in memory and you would use realloc every time you added or removed anything from the array so it would always be contiguous and easily searchable.
However, you are using arrays so we are back to the defined size at compile time. Since you know the size at compile time you should be able to split the array into four or more pieces. If you divide 16 by however many subsets you want and take away 1 (the result needs to be even for this to work) you can address a subset by passing 0 for 0-3, 1 for 4-7, 2 for 8-11 and 3 for 12-16. In code it would look something like this
void funciton(int array[16], int subset) {
int i = 0;
for(i = 0;i < 4;i++) {
array[(subset * 4) + i] = foobar;
}
}
This question already has answers here:
Why can't I assign arrays as &a = &b?
(2 answers)
Closed 9 years ago.
I wrote this piece of code
#include <stdio.h>
struct foo
{
int foo1[3];
};
int main(void)
{
int a[] = {1, 2, 3};
struct foo test;
test.foo1 = a;
printf("%d\n", test.foo1[0]);
return 0;
}
It gives compile error saying that it cannot convert int * to int[3].
I know that array names will decay into pointers in expressions, but is there a way of suppressing that since I do need an array here?
As the others said, there is not direct assignment operators that will copy an array. You have to use memcpy() instead
memcpy(test.foo1, a, sizeof(a));
This is one source of errors in C because the sizeof() needs to be large enough to copy all the data but not too large so as not to overwrite data at tests.foo1. The best practice, I would imagine, is to test that both arrays are the same size before doing the memcpy().
This is one of the basics of C, arrays cannot be assigned.
In C and in C++ there is no way to assign a value to an whole array. It is also not possible to assign an array the values of an other array (even if the dimension would match).
You cannot assign arrays in C. However, you can assign objects of user-defined type, even if those contain an array. So peraps rewrite it like this:
struct foo a = { { 1, 2, 3 } };
struct foo test;
test = a;
Or of course just initialize the object correctly immediately:
struct foo test = { { 1, 2, 3 } };
Arrays are not first class objects in C. You can't copy (assign), compare, pass, or return an array. You copy an array into another array element by element. You also compare two arrays element by element. You pass a pointer to a first element of the array and similarly return a pointer to the first element of a dynamically allocated array. Therefore test.foo1 = a; is wrong. You have two choices here.
#include <stdio.h>
struct foo {
int foo1[3];
};
int main(void) {
int a[] = {1, 2, 3};
struct foo test;
int len = *(&(test.foo1) + 1) - test.foo1; // length of the array test.foo1
int i = 0;
for(i = 0; i < len; i++)
test.foo1[i] = a[i]; // copy the array element-wise
printf("%d\n", test.foo1[0]);
return 0;
}
You can also directly copy all the bytes from the array a in main to the array test.foo1 using memcpy.
memcpy(test.foo1, a, sizeof a);
This copies all the bytes of the array a into the array test.foo1. Therefore the array test.foo1 must be large enough else it will lead to undefined behaviour or even segfault.
This question already has answers here:
How can I get the size of an array from a pointer in C?
(16 answers)
Closed 9 years ago.
For the following scenario, how can I get the size (3) of the array a via the pointer c? What is the pattern for solving this sort of problems?
struct struct_point {
int x;
int y;
int z;
};
typedef struct struct_point point;
int test_void_pointer () {
point a[3] = {{1, 1, 1}, {2, 2, 2}};
void * b;
point * c;
b = a;
c = b;
/* get_size_p (c) */
}
You can't. The pointer is just an address, a number, and it doesn't hold any information about the data it points to except its type.
Side note: that's why they say "arrays decay to pointers". They "decay" because inherently a pointer holds less information compared to an array.
As nims points out in the comments when passing an array to a function, it automatically decays to a pointer to the first element - and doing sizeof in the function doesn't yield the expected result. Incidentally there's also a C FAQ about this.
In C, no information about the size of the array is stored with the array. You have to know how big it is to work with it safely.
There are a few techniques for working around this. If the array is declared statically in the current scope, you can determine the size as:
size_t size = (sizeof(a) / sizeof(a[0]);
This is useful if you don't want to have to update the size every time you add an element:
struct point a[] = {{1, 1, 1}, {2, 2, 2}};
size_t size = (sizeof(a) / sizeof(a[0));
But if you have an arbitrary array, that has been passed in from somewhere else, or converted to a pointer as in your example, you'll need some way of determining its size. The usual ways to do this are to pass the size in along with the array (either as a separate parameter, or as a struct containing the array), or if the array is of a type which can contain a sentinel value (a value of the given type that is not valid), you can allocate an array one bigger than you need add a sentinel to the end of the array and use that to determine when you've reached the end.
Here's how you might pass in a length as a separate argument:
struct point myfunction(struct point array[], size_t n) {
for (size_t i = 0; i < n; ++i) {
struct point p = array[i];
// do something with p ...
}
}
Or as a structure containing the length:
struct point_array {
size_t n;
struct point elems[];
}
struct point myfunction(struct point_array a) {
for (size_t i = 0; i < a.n; ++i) {
struct point p = a.elems[i];
// do something with p ...
}
}
It would probably be hard to use sentinel values with an array of struct point directly, as there is no obvious invalid value that is still of the same type, but they are commonly used for strings (arrays of char which are terminated by a '\0' character), and arrays of pointers which are terminated by a null pointer. We can use that with struct point by storing pointers to our structures rather than storing them inline in the array:
struct point *myfunction(struct point *a[]) {
for (size_t i = 0; a[i] != NULL; ++i) {
struct point *p = a[i];
// do something with p ...
}
}
There's a way to determine the length of an array, but for that you would have to mark the end of the array with another element, such as -1. Then just loop through it and find this element. The position of this element is the length.
So, I was reading about pointers, and came across the concept of pointers to arrays. The thing is that a pointer to an array doesn't really seem useful at all, since instead of using a pointer to have an offset to access an array element, I could just get the element directly. However I feel as if I'm missing the reason why these can be useful.
So, in short, What is the point of pointers to arrays; How and why should they be used, and do they have any practical applications?
Edit: I meant this in the context of normal/simple arrays such as:
int array[5];
Edit: As Keith Pointed out, I'm specifically asking about pointers to arrays, for example char (*ptr)[42] which is a pointer to a 42-element array of char.
Unfortunately some answers you received show misbeliefs about pointers and arrays in C, in brief:
1) Pointer to array is not the same as pointer to first element.
2) Declaring array type is not the same as declaring pointer.
You can found full description in C faq part related to common confusion between pointers and arrays: http://c-faq.com/aryptr/index.html
Adressing your question - pointer to array is usefull to pass an entire array of compile-time known size and preserve information about its size during argument passing. It is also usefull when dealing with multi dimensional arrays when you what to operate on subarray of some array.
In most expressions, an object of type "array of T" will degrade to the address of the first array element, which will have the type "pointer to T". In this sense, a pointer type can be used to represent an array of items, and is used to do so when there is need to dynamically allocate an array.
// ptr used to dynamically allocate array [n] of T
T *ptr = malloc(n * sizeof(*ptr));
In the case of a pointer to an array, then, it can be used to represent an array of arrays, and/or dynamically allocate an array of arrays. So, a pointer to an array can be used to represent a 2-dimensional array.
// ptr used to dynamically allocate 2 dimensional array [n][10] of T
T (*ptr)[10] = malloc(n * sizeof(*ptr));
True pointers to arrays (which haven't really been addressed so far) are uncommon since arrays decay to a pointer to their first element in most contexts, and since arrays are contiguous in memory by definition that is usually all that is needed. They are also somewhat impractical compared to other pointer types since array types cannot be assigned to. They are similar to function pointers in that respect.
The biggest practical difference comes from the fact that they preserve the size of the array in situations where it would otherwise be lost to pointer decay, such as function calls and returns. Take the following code for example
void function(char (*array)[10]) {
for(size_t i = 0; i < sizeof(*a); i++);
(*a)[i] = i;
}
...
char a[10];
function(&a);
Besides allowing for this application of sizeof (which isn't terribly useful since the size is known as part of the parameter), this enforces the exact size of the passing argument as part of the type, which function(char array[10]) won't do, even with [static 10].
Returning has an unusual syntax:
char (*function(void))[10] {
static char array[10];
// do something with our static array
return &array;
}
char (*a)[10] = function();
// or even
char (*b)[sizeof(*function())] = function();
I don't think I've ever come across an application of this in the wild, but it is at least possible (and legal).
If you have an array of arrays a pointer to an array becomes useful, like in the following:
typedef float Point[3];
Point points[10];
Point *p;
for (p=points;p<points+10;++p) {
...
}
Here is real-world example of using pointers to arrays:
typedef double t_matrix33[3][3];
// Result = AB
// const double (* M1)[3], const double (* M2)[3], double (* Result)[3]
void Matrix33xMatrix33( const t_matrix33 M1, const t_matrix33 M2, t_matrix33 Result ) {
t_matrix33 copy;
const t_matrix33 * A = ( const t_matrix33 * )M1; // const double (* A)[3][3] = const double (* M1)[3]
const t_matrix33 * B = ( const t_matrix33 * )M2; // const double (* B)[3][3] = const double (* M2)[3]
int Raw;
int Col;
int i;
// !!! Make copies if Result is the same as M1 and/or M2!
//const double (* A)[3][3] == double (* Result)[3]
if( A == ( const t_matrix33 * )Result ) { // cast is must -- to get rid of gcc warnings
memcpy( copy, A, sizeof( t_matrix33 ) );
A = ( const t_matrix33 * )copy;
if( B == ( const t_matrix33 * )Result ) {
B = ( const t_matrix33 * )copy;
}
}
else if( B == ( const t_matrix33 * )Result ) {
memcpy( copy, B, sizeof( t_matrix33 ) );
B = ( const t_matrix33 * )copy;
}
for( Raw = 0; Raw < 3; ++Raw ) {
for( Col = 0; Col < 3; ++Col ) {
Result[ Raw ][ Col ] = 0;
for( i = 0; i < 3; ++i ) {
Result[ Raw ][ Col ] += (*A)[ Raw ][ i ] * (*B)[ i ][ Col ];
}
}
}
};
Thanks to A and B pointers we can avoid redundant memcopies in the case of M1 and/or M2 are not the same as Result
The one I can think of at the moment is (I am sure there are others as well), you want to make multidimensional array, however you don't have any data at the moment to save in the 2nd or 3rd dimension of the array. You don't want to waste the memory by conserving the space for 2nd and 3rd dimension of the array but you plan to allocate the memory later when you have data to store, thats when pointers to arrays come handy.
Eg.
for (int i=0; i<10; i++)
(*x)[i] = malloc(N * sizeof(*x));
// take input or put data in the array
Representation Of 2d Array In C:
This site explains it quite well. This should help you removing any confusions.