---EDIT--- The array was previously initialized as a pointer (*arr).
For a problem I´m trying to solve, I need to go through an array of variable size and started using this loop:
int arr[] = {3, 5, 10, -2, -1, -3}; // Just an example
int i = 0;
while(arr[i]) {
//do something
i++;
}
It seems that after going through the array I initiliazed, the code finds some random values stored in memory and keeps counting, even though the array I´m trying to work with has long been passed.
How could I avoid this?
Best regards!
int *arr is not the array.
int is not the type which should be used as the index. Use size_t instead
Array
int arr[50]; <- this the array
you can get the size of the array dividing its size by the size of the element.
pointer
int *ptr; it only references the int object. You cant get the size of the allocated memory by dividing size of the pointer by size of reference object
Related
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.
Consider the code:
#include <stdio.h>
int a[] = { 1, 2, 3 };
int b[];
int main() {
b = { 4, 5, 6 };
return 0;
}
This of course is illegal.
main.c:7:9: error: expected expression before '{' token
7 | b = { 4, 5, 6 };
| ^
I need to initialize array b in a function. How to do that?
I know one way, but it's... IDK, really?
#include <stdio.h>
int a[] = { 1, 2, 3 };
int b[3];
int main() {
b[0] = 4;
b[1] = 5;
b[2] = 6;
return 0;
}
Is it the only way of doing that?
EDIT:
It's very hard to explain my intent.
Let's say I define items in code. Right? Is that clear? In code, means - it's static, not dynamic. Not runtime. Not "variable length". Let's say it will be 5 items, right? So why don't I just say 5 and set the fixed length to 5?
The reason for this is, I don't have to write:
int a[5] = { 1, 2, 3, 4, 5 };
```c
but instead I can write
```c
int a[] = { 1, 2, 3, 4, 5 };
That saves me the redundant step of counting my items manually, because the compiler counts the items for me. It also allocates the memory on stack for them for me. No need to call malloc.
And here goes the hard to explain part:
Imagine instead of 1, 2, 3, 4 I have structures. They are not numbered, they contain various data types.
Imagine, that later in time I add an additional item to my array, because it will become necessary at a certain point of the project development. To be absolutely clear: this is not by any means dynamic. I will never need a single item more during the runtime. It will be added to the code and committed to Git. And it will stay there, maybe to the end of the program's life.
Imagine I add the item, but I forget to update the items count. It's a super common bug.
The whole point for me is to learn, whether a syntax in C exists allowing to omit the item count by initializing array inside a function. Now I suspect - it is not possible. I can either make such initialization when defining a variable, but not when assigning to the variable, even if it's the only assignment made to that variable.
I'd avoid to allocate more bytes than necessary, also performing more operations than necessary because it's for embedded and I really aim to cut that kind of costs. I also learn how to do the things the correct way, even if I technically could waste some resources.
Additional problem with my real code is some data for the items is not available before a function is called.
So my temporary solution is just to specify the array length. And then remember to update it when I add or remove items DURING DEVELOPMENT. That should work. If it's the correct way of doing that, than it's fine and I'm done. If not, I'd be happy to learn how to do it a better way.
The proper term is variable length array. This is an array whose size is determined by a non-constant expression. Its size is set at execution time when program execution reaches the definition of the array. (“Flexible” is used in the term flexible array member, which is an array that is the last member of a structure and that adapts to the memory allocated for the structure.)
The size of a variable length array must be given where the array is defined, as with int b[n];. You cannot leave the size incomplete, as with int b[];, and specify it later.
C has no grammar for assigning directly to an array. You can assign values to individual elements, and a method for specifying values in aggregate is to use memcpy to copy them from another array, which can be a compound literal:
#include <stdio.h>
#include <string.h>
int main(void)
{
int n = 3;
int b[n];
memcpy(b, (int []) { 4, 5, 6 }, sizeof b);
for (int i = 0; i < 3; ++i)
printf("b[%d] = %d.\n", i, b[i]);
}
The first thing that's wrong is
int b[];
This makes no sense. gcc treats this as the following
int b[1];
This is most definitely wrong. You want
int *b;
Cloning a would be done as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t size = sizeof( a );
b = malloc( size );
if ( !b ) {
perror( "malloc" );
exit( 1 );
}
memcpy( b, a, size );
Don't forget to free( b );.
Imagine I add the item, but I forget to update the items count.
I think what you're getting at is that you need the size of the array, but you don't want to hardcode it.
No problem. Use this:
int a[] = { 5, 6, 7 };
size_t n = sizeof( a ) / sizeof( *a );
Then you can do stuff like this:
for ( size_t i = 0; i < n ; ++i )
do_this( a[i] );
or
do_that( a, n );
At no point was 3 mentioned, so the code keep working even if you change the initialization of a to the following:
int a[] = { 5, 6, 7, 8 };
The whole point for me is to learn, whether a syntax in C exists allowing to omit the item count by initializing array inside a function
There's nothing special about arrays in functions. Just like outside of functions, you will need to provide a size (int b[...];) or an initializer (int b[] = ...;). Without this, the program wouldn't know how much space to allocate.
But while you say this is the point, it's obviously not. You appear to want to ensure that two arrays are the same size, as you make clear in your following paragraph.
I'd avoid to allocate more bytes than necessary, also performing more operations than necessary because it's for embedded and I really aim to cut that kind of costs. I also learn how to do the things the correct way, even if I technically could waste some resources.
If the array fits on the stack, you can use the following to allocate it on the stack instead of using malloc.
void do_that( int *a, size_t n ) {
int b[n];
...
}
These are called variable length arrays, and it was an addition to C99. (They are variable-length in the sense that every instance of an array created by this code can have a different length. But the created arrays are fixed in size like every C array.)
Imagine I add the item, but I forget to update the items count. It's a super common bug.
The crux of this problem is that you should not code the items count as some constant. Instead use code to calculate to items count value or simply use the size of b[].
#include <assert.h>
#include <string.h>
// Array b exist _someplace_ of some size
void assign_b() {
// Form the initialization list.
same_type_as_b_element b_values[] = { 8, 6, 7, 5, 3, 0, 9 };
// Same size?
static_assert(sizeof b == sizeof b_values), "Mis-matched sizes in b[]");
// Copy to b
memcpy(b, b_values, sizeof b);
}
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
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 have bug when calling to a function dynamic_arr - somehow I loose all my array and only
the first element being returned.
In my code my main calls a function that dynamically needs to create an array
and after the user will insert the elements of the array all the array needs to be passed to
function funcdosomthing.
But at the moment function funcdosomthing gets only the first element and not all the array.
Just to make clear that everything else works - when I don't use function dynamic_arr and
set the array manualy int a[] = {1, 0, 2}; everything works fine and function funcdosomthing gets all the array with 3 elements.
Here's my code:
int *dynamic_arr(int n)
{
int i, *a;
a = (int*)calloc(n, sizeof(int));
for(i=0;i<n;i++) scanf("%d",a+i);
return a;
}
int mainprograma()
{
int n,*a,i;
scanf("%d",&n);
a=dynamic_arr(n);
funcdosomthing(a, sizeof a / sizeof a[0]);
...
You are trying to calculate the size of an array from a pointer to a dynamic array.
sizeof a / sizeof a[0]
In C you simply cannot find out the length of an array if you only have a pointer to the array. The code you are using is appropriate if you have an array, but you don't have an array, you have a pointer.
So, if you had declared a like this
int a[3];
or this
int a[] = {0, 1, 2};
then a would be an array rather than a pointer and the sizeof code above would be applicable.
Fortunately you know how big the dynamic array is because you just created it. It has n elements. So you must write your call to funcdosomthing like this:
funcdosomthing(a, n);
Why do you try to find the size when you already know the size?!
You should use n instead of calculating the size like sizeof a / sizeof a[0]. And more over, sizeof(a) will give your expected result iff a is an array. In this case, it is a pointer-to-memory-which-can-store-n-integers.