Non-defined sized array in C - c

I am learning C using learn-c.org, and on this page it says I can use
char name[] = "John"
In its own example on the bottom frame of the page, if I do
char last_name[] = "Doe"
no errors are reported but the program won't run. It will only run if I do char last_name[4] or greater... so the question:
Can an array be declared without a size or do I need to know the max values the array will hold? So kind of a second question, if I do int array[10], what would happen if I needed more than 10 values?

Can an array be declared without a size or do I need to know the max
values the array will hold?
Depends on whether you initialize it. When you initialize it, the compiler will count the elements for you. So, this is valid:
int a[] = { 0, 1, 2, 3 };
This effectively creates an array of 4 elements. If you provide a size and initialize the array, then if the size is greater than the number of elements, the first elements are initialized accordingly, and the rest of them are initialized to their default initialization value (0 for integers, null for pointers, etc.).
If the size is less than the number of elements, it is an error.
If you do not initialize, then you have to declare the size.
With this:
char last_name[] = "Doe";
The compiler creates an array of 4 chars (one of them is the null terminator).
If I do int array[10], what would happen if I needed more than 10
values?
You can't do anything. If you need more than 10, you need a bigger array.

You can either have an array with fixed size or a pointer to an array (starts with *) that can have any size (up to its limits that is).
As for the second question, the program would crash as the array would get out of its boundaries.

Related

How to create an array without declaring the size in C?

I'm trying to create a int and a float array without a size (it might be 0 or it might increment while the user use the program).
I was trying to do the follow:
int bills[];
float totalAmount[];
I can't assign a max size because I'm printing each array with a for loop (If I assign a size of 99 I'll print 99 lines, and I don't want that).
C does not support arrays with a dynamic number of elements. The number of elements of an array must be determined either at compile time or since C99 can be evaluated at runtime at the point of creation. Once the array is created, its size is fixed and cannot be changed. There are a few cases where the size is not explicitly specified between the [], either in array definitions or in array declarations.
You can define an array without an explicit size for the leftmost dimension if you provide an initializer. The compiler will infer the size from the initializer:
int a[] = { 1, 2, 3 }; // equivalent to int a[3] = { 1, 2, 3 };
int m[][2] = {{ 1, 2 }, { 3, 4 }}; // equivalent to int m[2][2] = {{ 1, 2 }, { 3, 4 }};
char s[] = "Hello world\n"; // equivalent to char s[13] = "Hello world\n";
Note how the compiler adds the implicit null terminator in the string case.
You can declare an array without a size specifier for the leftmost dimension in multiples cases:
as a global variable with extern class storage (the array is defined elsewhere),
as a function parameter: int main(int argc, char *argv[]). In this case the size specified for the leftmost dimension is ignored anyway.
as the last member of a struct with more than one named member. This is a C99 extension called a flexible array.
The compiler has no information on the actual size of these arrays. The programmer will use some other information to determine the length, either from a separate variable or from the array contents.
In the case of a function argument, the array is passed as a pointer and even if the number of elements is specified, sizeof(argv) evaluates to the size of a pointer.
You don't declare an array without a size, instead you declare a pointer to a number of records.
so, if you wanted to do
int bills[];
The proper way to do this in C is
int* bills;
And you will have to allocate the size at some point in time and initialize the array.
bills = (int*)malloc(sizeof(int)*items);
The same goes for arrays of other data types. If you don't know the size of the array until runtime, you should use pointers to memory that are allocated to the correct size at runtime.
You could use a combination of malloc() (or calloc()), realloc() and free() to achieve this.
Memory can be allocated as blocks of a fixed size rather than reallocating memory for each number to be stored.
Let's define a macro (or a const if you like) BLOCK_SIZE.
#define BLOCK_SIZE 10
First declare a pointer of appropriate type and allocate the first block.
Note that malloc() as well as realloc() return NULL if some error occurred due to reasons like insufficient memory.
int *ptr=malloc(sizeof(int)*BLOCK_SIZE);
if(ptr==NULL)
{
perror("some error");
return 1;
}
Now declare a variable to store the maximum possible index as per the currently allocated memory (to avoid illegal memory access).
int max_index = BLOCK_SIZE-1;
Now use a loop.
for(int i=0; ; ++i)
{
if(i > max_index)
{
ptr=realloc(ptr, (max_index+1 + BLOCK_SIZE)*sizeof(int));
if(ptr == NULL)
{
perror("insufficient memory!");
break;
}
printf("\nRealloced!");
max_index += BLOCK_SIZE;
}
scanf("%d", &ptr[i]);
printf("\n%d: %d", i, ptr[i]);
}
In each iteration, we check if i is greater than max_index. If it is, another block is allocated using realloc() before reading the value.
Don't forget to deallocate the memory once you are done using it.
free(ptr);
Also, as discussed in this post, malloc() is effectively the same as realloc() with the latter's first argument NULL.
And in the code you posted, there's no need to explicitly cast the return value of calloc() as what's returned is a void pointer which would implicitly be converted to the target pointer type.
See this and this.
i think you can give it a max size ,if you only want to show the first few elements you can put a a for loop upto that element only,same goes for input if u want to initiallize first 30 elements put a for loop upto 30.

int array element not initialized to zero in C

I created an array of 10 elements in C inside of main and declared values for only some of the elements. When printing out the array I noticed that one of the elements, which was left untouched, was not initialized to zero. Instead, it was initialized to a different large value every time (i.e. 1491389216). I then commented out all of my code and just left the array as I initially declared it.
When running the code, the first 8 elements of the array were initialized to zero, the 9th element in the array was being initialized to a large value (like 1491389216) which changed every time, and the last element was consistently being initialized to the same non-zero number.
Does anyone have any idea why this is happening?
Local (automatic) arrays are not initialized unless you explicitly initialize them. Otherwise they contain whatever random data already occupies the memory.
If you want to zero out all of the elements when declaring the array, you can do this:
int arr[10] = {0};
Or:
int arr[10] = {};
Depending on your compiler (GCC allows this, unless you specify -pedantic).
Or, just use memset() instead:
int arr[10];
memset(arr, 0, sizeof(arr));
Similarly, memory allocated by malloc() — or extended by realloc() — is not initialized; use calloc() to zero-initialize such data:
int *arr = (int*) calloc(10, sizeof(int));
...
free(arr);

C: size of *array[x]?

I have a question that should be fairly straightforward (I hope).
In c, the size of an array delcared as int array[10][10];,
for example, I understand as having 10 spots in which to store 10 integers. However, what's the size of an array declared as int *array[10];? I know that *array has 10 elements, but how many elements does array have?
This is a hole in my understanding I would really like to clear up. Thanks for any help!
int *array[10]; is an array of 10 int *s, so the number of elements is 10.
To elaborate, for int *array[10];, ty type of array variable is int * [10], an array of 10 elements of type pointer to integers.
The array size would be 10 * sizeof pointer-to-integer-in-your-platform.
You have to understand the declaration in C.
Start dividing it in parts:
int array[10][10];
array is the name of the variable, the part [10] means that it is an array of 10 arrays of int, each array holding 10 elements (the second [10]).
Now:
int * array[10];
array is the name of the variable, the part [10] means that it is an array of 10 elements of type int * (integer pointers not integers as before).
The sizes in the firs case will be 10 times the size of an array of 10 integers = the space required for 100 integers.
In the second case will be the size to hold 10 pointers to integer.
As side note maybe your confusion comes from the fact that C allows access to elements of both declaration in the same way. I.e. the following will get the 5th integer of the second array:
int b = array[2][5];
But the difference remains substantial because in the first declaration the compiler will allocate contiguous space to hold all 100 integers (organized, as per C allocating method, as 10 arrays of 10 integers each in succession), in the second case will be allocated only an array of 10 pointers each pointing to the location of an array of 10 integers. And the 10 arrays will not be allocated, nor the pointers initialized.
In that case it is programmer responsibility to allocate 10 arrays of int and assign the address of each one to the array of pointers.
Another point to clarify (thanks to alk to have pointed it out) is that in the case of the array of pointers the second dimension is undefined, meaning that each array of int pointed can be of 1, 10, 1000 or whatever elements.
how many elements does array have?
int *array[10];
array is array of 10 pointers to int, the same as int* array[10] - so array has 10 elements (each element being a pointer).

Number of array elementsbof dynamic allocated array in C

I have problems finding the number of array elements in my dynamical allocated array.
If I have a normal Array I know how to find out how much elements are in there with:
int array[] = {1,2,3};
printf("Number of array elements: %i\n",(int)(sizeof(array) / sizeof((array)[0])));
this prints me:
Number of array elements: 3
But when I want to dynamically allocate an array and know its size I can't get it working the same way:
int *array;
array = malloc(3*sizeof(int));
printf("Number of array elements: %i\n",(int)(sizeof(array) / sizeof((array)[0])));
This always gives me:
Number of array elements: 2
No matter how much how small or big I make the allocation it always prints
2
Please can someone help?
The reason you see different size is because the underlaying data isn't the same.
In you first example, you have statically compiled array of integers. This array elements are all aligned in memory and array is the array. Using sizeof(array) allows you to get the overall size of this array.
In the second example, you have a dynamically allocated pointer on an array of integers. This is totally different in memory. The array variable isn't the array practically speaking. It's the pointer to the first element. Using sizeof(array) here returns the size of the pointer on the first element, hence 8.

how to get the size of array using the pointer to this array in C? [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 8 years ago.
I have the following code in C:
int array[5] = {0,1,2,3,4};
int * p = &array[0];
how to use the pointer p to get the size of this array p point to?
Sorry, this is actually impossible. The size of an array is not saved anywhere. You'll have to do it yourself.
It can't be done just from a pointer. The pointer is literally the address in memory of the first element of the array. The array size is not automatically associated with this pointer. You must keep track of the size yourself.
One workaround you can use is to reserve a special value for your array elements, say -1. If you can arrange for your last element to always have this value, then you can always find the end of the array by searching through it for that value. This is why strings have a null terminator, so strlen() and family can find the end of the string.
The short answer: In C, an array size cannot be retrieved from a pointer. The size must be passed separately.
The slightly-less-short answer: In C, a pointer is just an address to a spot in memory. The pointer does not even guarantee that there is a valid array or variable here; it is just a descriptor of a memory location.
In fact, in C, the concept of an array "size" is somewhat loose. A certain amount of consecutive memory can be allocated, but there is no checking as to if a pointer leaves this memory.
For example:
int a[] = {1, 2, 3};
int b = a[7];
will compile properly. C does not have any bounds checking!
you can not know the size of array using pointer to it. you cant determine since there is no way to know the end of array or to know that we reached the last element of array.
So, after reading 5 previous answers, here a better one:
a) You cannot get the element count of an array using a pointer.
Common workaround are:
Using a sentinel value (see C-String aka asciiz)
Passing the length separately. (see counted strings using mem*())
Actually using a struct, resp. reserving element 0 (or -1) for a lenght value. (also see counted strings).
Just allocate a whopping big amount of memory you know will suffice and not bother with the actual length at all. Getting this wrong is fun and easy to do.
b) You can get the element count of an array using the array name:
struct foo[my_expr];
ìnt count = sizeof array / sizeof *array;

Resources