I need to initialize array of
array[921600] = {229407, 229407, 229407,...,226851};
elements, I allocated array for 921600 elements and initialized array in function:
setArray(array);
and function looks like this:
Void setArray(Uint8 *array){
array[921600] = {229407, 229407, 229407,...,226851}; //shorten
}
and then I get error in compiler: error: expected an expression.
When I initialize elements one by one it works like this:
Void setArray(Uint8 *array)
{
*(array + 0) = (3);
*(array + 1) = (2);
*(array + 2) = (2);
}
In C, you can initialize an array as you declare it [^1]
For example:
int digits[] = { 3, 1, 4, 1, 5, 9, 2, 6 }; // Initialize an array of 8 numbers
However, after an array is created, you cannot use the same syntax to assign it. Initialization and Assignment are two different operations with different rules.
The closest thing to a bulk assignment I know of is an ugly memcpy using a compound-literal.
memcpy(digits, (int[]){3,1,4,1,5,9,2,6}, sizeof(digits));
Example Code:
#include <stdio.h>
#include <string.h>
int main(void) {
int digits[8];
memcpy(digits, (int[]){3,1,4,1,5,9,2,6}, sizeof(digits));
for(int i=0; i<8; ++i)
{
printf("%d", digits[i]);
}
return 0;
}
But that technique would be extremely difficult (and wasteful) to do on an array of 921600 elements. For a very big array, the data should likely be loaded from a compiled resource or a text file or a similar external source.
[^1]: Except for VLAs. VLAs cannot be initialized this way.
First of all, this:
array[921600] = {229407, 229407, 229407,...,226851} //shorten
doesn't assign the entire array - it's attempting to assign a brace-enclosed list to a single array element (which is a syntax error), and that element is one past the end of the array (if there are 921600 elements in the array, then they are indexed from 0 to 921599).
You cannot assign an entire array's contents using the = operator - if you want to set all elements to the same value you can use memset, otherwise you'll have to assign elements individually.
Your compiler should also be yakking on Void and Uint8 - are you sure you don't mean void (C is case-sensitive) and uint8_t? And if you mean for the elements to be 8 bits unsigned, then they won't be able to represent values like 229407 or 226851.
This doesn't work:
array[921600] = {229407, 229407, 229407,...,226851};
Because you're actually attempting to assign (not initialize) a single value in array, and the {...} syntax is only valid for an initialization.
If you have some fixed set of values you're going to use to set your array, you can place them in another array and copy them in:
void setArray(uint8 *array)
{
static const int src[921600] = {229407, 229407, 229407,...,226851};
memcpy(array, src, sizeof src);
}
By making the source array static, you avoid having a large temporary array that could potentially blow up the stack.
Related
Say I want to loop over an array, so I used a basic for loop and accessed each element in it with the index but what happens if I don't know how long my array is?
#include <stdio.h>
#include <stdlib.h>
int main(){
int some_array[] = {2,3,5,7,2,17,2,5};
int i;
for (i=0;i<8;i++){
printf("%d\n",some_array[i]);
}
return 0;
}
This is just a simple example but if I don't know how big the array is, then how can I place a correct stopping argument in the loop?
In Python this is not needed since the StopIteration exception kicks in, but how can I implement it in C?
Just do like this:
for (i=0; i<sizeof(some_array)/sizeof(some_array[0]); i++){
printf("%d\n",some_array[i]);
}
But do beware. It will not work if you pass the array to a function. If you want to use it in a function, then write the function so that you also pass the size as argument. Like this:
void foo(int *arr, size_t size);
And call it like this:
foo(some_array, sizeof(some_array)/sizeof(some_array[0]));
But if you have a function that just take a pointer, there is absolutely no standard way to find out the size of it. You have to implement that yourself.
You have to know the size of the array. That's one of the most important rules of C programming. You, the programmer, are always responsible for knowing how large your array is. Sure, if you have a stack array or a static array, you can do this:
int array[size];
int size_of_array = sizeof array / sizeof *array;
for (int i = 0; i < size_of_array; i++) {
// do something with each array[i]
}
But as you can see, you needed the variable size in the first place. So what's the point of trying to discover the size if you were forced to know it already?
And if you try to pass this array to any function
some_function(array); /
you have to pass the size of the array too, because once the array is no longer in the same function that declared it, there is no mechanism to find its size again (unless the contents of the array indicate the size somehow, such as storing the number of elements in array[0] or using a sentinel to let you count the number of elements).
void some_function(int *array) {
/* Iterate over the elements until a sentinel is found.
* In this example, the sentinel is a negative number.
* Sentinels vary from application to application and
* implicitly tell you the size of the array.
*/
for (int i = 0; array[i] >= 0; i++) {
// do something with array[i]
}
}
And if it is a dynamically-allocated array, then you need to explicitly declare the number of elements anyway:
int size = 10;
int *array = malloc(sizeof *array * 10);
So, to summarize, you must always know the size of the array. There is no such thing in C as iterating over an array whose size you don't know.
You can use sizeof() to get the size of the array in bytes then divide the result by the size of the data type:
size_t n = sizeof(some_array)/sizeof(some_array[0]);
In general, you can calculate the size of the array with:
sizeof(ArrayName)/sizeof(ArrayType)
but this does not work with dynamically created arrays
If I have:
typedef char pos[2]; /*btw I now know no one should do this*/
void someFunction(void) {
pos *s = malloc(sizeof(pos) * 2);
}
In the cases like this how s working? What is it? Arrays are like pointers except when you use sizeof on them you will get the "correct" size. So in this case the following means that s is going to be a pointing to a sizeof(char)*4 sized memory? But the type of s is a pointer to a pointer which means that you can't use s as a one dimensional array (or a pointer which points chars ) becouse you "still need to go through one level/layer of indirection/pointer". Or am I wrong?
How can I use s? As a 2 dimensional array or as a one dimensional one?
(If you are interested: I need this bc I want to return two pos from a function. Is there a better way? (despite fixing this and using a struct for storing position data instead of a 2-sized array))
This typedef costruct is just equivalent to:
#include <stdio.h>
void someFunction(void) {
char (*pos)[2];
pos = malloc(sizeof(*pos) * 2);
pos[0][0] = 1;
}
int main(void) {
someFunction();
return 0;
}
That means that pos is the pointer to two-elements array of char. You can use just like as two-dimensional array with fixed column size as two. Number of rows is controlled by malloc() call, in your case it happened to be two as well.
I'm modifying existing code for a new project. I was instructed to remove dynamic memory allocation and use static declaration.
There is a variable arrp, earlier it was a double pointer, to which memory will be allocated using malloc and will be accessed as 2D array.
Now i have changed it as pointer to array i.e: char (*arrp)[];
The size of the 2D array to which arrp points to will be known only at runtime. My problem is if size is not declared compiler throws error('char (*)[]' : unknown size)
Please refer the following code, i did something like this
char (*arrp)[]; //This will be from different module,
//I have declared as local variable for our reference
char (*parr)[2];
char arr[3][2];
parr = &(arr[0]);
arrp = (char (*)[])&(arr[0]);
//inside loops for i, j
...
printf("%c",parr[i][j]); // This works fine
printf("%c",arrp[i][j]); // Error :'char (*)[]' : unknown size)
....
//Some code
It not possible to get the size of array when arrp is declared. Is there any way to eliminate this error?
A pointer to an array helps in jumping over whole arrays at a time. ( ie with a single increment ) It does this through the knowledge of the column width of the array to be jumped. So without the knowledge of the column size, I am afraid, your pointer to an array will be of no use to you.
But if you have a modern compiler which supports variable length arrays ( C99 ), then its quite simple
int foo ( int m, int n )
{
int a[m][n];
int (*ptr)[n]=a;
a[0][2] = 78;
printf("%d", ptr[0][2]);
}
I need to store an array of point (x,y). I read the points from a file, and the number of points are not constant, but i can get it at the first line of the file. So i write a procedure load() to loading the points from the file and store them in a global array. It doesn't work.
My code:
int *array[][]; // this is a pointer to a 2-dimensional array??
void load(){
..
int tempArray[2][n]; //n is the first line of the file
..
array = tempArray;
}
You're trying to return a pointer to memory that is local to the function that defines the variable. Once that function stops running ("goes out of scope"), that memory is re-used for something else, so it's illegal to try and reference it later.
You should look into dynamic allocation, and have the loading function allocate the needed memory and return it.
The function prototype could be:
int * read_points(const char *filename, size_t *num_points);
Where filename is of course the name of the file to open, num_points is set to the number of points found, and the returned value is a pointer to an array holding x and y values, interleaved. So this would print the coordinates of the first point loaded:
size_t num_points;
int *points;
if((points = load_points("my_points.txt", &num_points)) != NULL)
{
if(num_points > 0)
printf("the first point is (%d,%d)\n", points[0], points[1]);
free(points);
}
This declaration of yours does not work:
int *array[][]; // this is a pointer to a 2-dimensional array??
First, it is trying to declare a 2D array of int *. Second, when you declare or define an array, all dimensions except the first must be specified (sized).
int (*array)[][2]; // This is a pointer to a 2D array of unknown size
This could now be used in a major variant of your function. It's a variant because I misread your question at first.
void load(void)
{
...
int tempArray[n][2]; // Note the reversed order of dimensions!
...
array = &tempArray;
...there must be some code here calling functions that use array...
array = 0;
}
Note that the assignment requires the & on the array name. In the other functions, you'd need to write:
n = (*array)[i][j];
Note, too, that assigning the address of a local array to a global variable is dangerous. Once the function load() returns, the storage space for tempArray is no longer valid. Hence, the only safe way to make the assignment is to then call functions that reference the global variable, and then to reset the global before exiting the function. (Or, at least, recognize that the value is invalid. But setting it to zero - a null pointer - will more nearly ensure that the program crashes, rather than just accessing random memory.
Alternatively, you need to get into dynamic memory allocation for the array.
Your question actually is wanting to make a global pointer to a VLA, variable-length array, where the variable dimension is not the first:
int tempArray[2][n]; // Note the reversed order of dimensions!
You simply can't create a global pointer to such an array.
So, there are multiple problems:
Notation for pointers to arrays
Initializing pointers to arrays
Assigning global pointers to local variables
You can't have global pointers to multi-dimensional VLAs where the variable lengths are not in the first dimension.
You should minimize the use of globals.
A more elegant version might go like this:
typedef struct point_ { int x; int y; } point;
point * create_array(size_t n)
{
return calloc(n, sizeof(point));
}
void free_array(point * p)
{
free(p);
}
int main()
{
size_t len = read_number_from_file();
point * data = create_array(len);
if (!data) { panic_and_die(); }
for (size_t i = 0; i != len; ++i)
{
/* manipulate data[i].x and data[i].y */
}
free_array(data);
data = 0; /* some people like to do this */
}
You are trying to assign an array but in C arrays cannot be assigned.
Use memcpy to copy one array to another array. Arrays elements in C are guaranteed to be contiguous.
int bla[N][M] = {0};
int blop[N][M];
/* Copy bla array to blop */
memcpy(blop, bla, sizeof blop);
I have a char array
char *data[]= {"11", "22", "33", "44", "55"};
How can I add some extra items to it in the end? data[]="66";
I'd like a dynamic array in C.
Thanks
Arrays created using the [] syntax are not dynamic, the length is set at compile-time and cannot change.
UPDATE: Actually, C99 adds so-called "variable-length arrays", which can get their length at run-time. After they've been initialized, however, they can't shrink or expand so the below still applies.
However, an array is trivially expressed when you have pointers: an array can be represented as a pointer to the first element, and a length.
So, you can create a new array by dynamically allocating memory using malloc():
size_t array_length = 3;
int *array = malloc(array_length * sizeof *array);
if(array != NULL)
{
array[0] = 11;
array[1] = 22;
array[2] = 33;
}
You cannot use the {} list of elements here, that's only usable when initializing arrays declared using the [] syntax.
To grow the array, you can use the realloc() function to re-allocate the memory and copy the old values over:
size_t new_length = array_length + 1;
int *bigger_array = realloc(array, new_length * sizeof *bigger_array);
if(bigger_array != NULL)
{
bigger_array[new_length - 1] = 44;
/* We have successfully grown the allocation, remember the new address. */
array = bigger_array;
array_length = new_length;
}
Note that every time you call malloc() (or realloc()), it can return NULL if it failed to allocate the requested block. That's why the if statements are needed. I cut the initial size down a bit from your example to reduce the number of assignment-lines needed, to make the example shorter.
To make the above more efficient, typical dynamical array code uses two length values: one for the actual array (how many values are in the array right now) and one for the memory (how many values to we have room to store). By making the latter value grow in chunks, the total number of memory allocations can be cut down a bit, at the cost of some memory of course.
vc_vector
vc_vector* vector = vc_vector_create(0, sizeof(const char *), NULL);
vc_vector_push_back(vector, "11");
vc_vector_push_back(vector, "22");
vc_vector_push_back(vector, "33");
for (int i = 0; i < vc_vector_count(vector); ++i) {
printf("%s ", (const char*)vc_vector_at(vector, i));
}
// output: 11 22 33
vc_vector_release(vector);
Here is a macro based solution for a dynamic array in C with a very nice syntax to use. Works for any data type.
#include <stdio.h>
#include <stdlib.h>
#include <wondermacros/array/dynamic_array.h>
int main()
{
int* elems = NULL; /* Initialize a dynamic array. */
W_DYNAMIC_ARRAY_PUSH(elems, 1, 2, 3, 4); /* Push some elements. */
/* Iterate all elements. */
W_DYNAMIC_ARRAY_FOR_EACH(int, e, elems) {
printf("%d\n", e);
}
W_DYNAMIC_ARRAY_FREE(elems); /* Free the array only this way since there is a hidden header. */
}
The library uses Boost pre-processor library so Boost library needs to be there at build time.