int array element not initialized to zero in C - 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);

Related

Is a 2D Array an Array of Pointers?

If I have:
int A[10][20];
printf("%p",A[3]);
it will print the address of A[3][0].
However, I'd like to know if this one dimensional array A[3] containing pointers really exists, or it is calculated in some way.
The way you have defined A means that the compiler will allocate for it a contiguous block of memory large enough to hold 10 x 20 (200) integers; see here (scroll down to "Multidimesional arrays"). As I'm sure you realize, if you were to do printf("%p", A); you would see the address of the beginning of that allocated block.
Now, when the compiler sees the expression A[3], it will add what it calculates as the necessary amount of "integer sizes" to the base address (that of A, or A[0][0]); in this case, it will add "3" (the index specified) multiplied by the combined size of all the other dimensions (in this case, there's only one, which is 20).
So, in your case, there is no actual array of pointers; just a memory block that the compiler can interpret according to how you described any part(s) of it.
However, in a more versatile approach, one can actually define a 2D array in terms of an actual array of pointers, like so:
int **A;
A = malloc(10 * sizeof(int*));
for (int n = 0; n < 10; ++n) A[n] = malloc(20 * sizeof(int));
In this case, using printf("%p",A[3]); would still be valid, but it would give a very different offset value from printf("%p",A); or printf("%p",A[0]);.
It's also, perhaps, worth noting that, even though these two different declarations for A can both resolve an individual element through an expression like A[i][j] (but the compiler would evaluate the addresses differently), there is here scope for major confusion! When, for example, passing such an array to a function: if the function expects data allocated in the second form, and you give it an array defined in the first form (and vice versa), you're gonna get major undefined behaviour .
yes there is a way to calculate the position:
for A[i][j]
the position of the memory block will be
pos = A + i*(number_of_columns_in_each_row) + j
here A is the pointer to the first element of the array
However, I'd like to know if this one dimensional array A containing pointers really exists, or it is calculated in some way.
The way you defined the array A :
int A[10][20];
does not contain any pointers as elements of the array. it contains only integer elements.
if you want to make an array of pointers, which should be assigned to int-variables is defined like that:
int *A[10][20];
You also can set a pointer to the start of the array, which means element [0] [0]
by using:
int *pointer;
int *A[10][20];
pointer = &A;
You also be able to set the pointer slightly forwards according to each element by increase the pointer.
pointer++;

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.

Size of 2d pointers

I'm trying to improve my knowledge with pointers by making an pointer who points to another pointer that is practically a string.
Now I want to get size who normally I could get fromsizeof(foo[0])/sizeof(foo[0][0])
Pointer form
char** foo;
sizeof(test)/sizeof(*test) doesn't indicate the number of elements anymore with your declaration, because the compiler doesn't know what is the pointer pointing to, because sizeof() is a compile time operation and hence not dynamic.
To find no of elements, you can add a sentinel value:
char **test = {"New York", "Paris", "Cairo", NULL};
int testLen = -1;
while(test[++testLen] != NULL){
//DO NOTHING
}
You will never get the size of a block of memory where a pointer points to... because there can be anything.
test simply points to a place in memory where some other pointers are stored (to the first one). Each pointer will again lead to another place in Memory where some character values are stored. So, your test variable contains a simple number (the index of a place in Memory) and depending on your operating System sizeof(test) will maybe have 4 bytes or 8 bytes as result regardless of the size of the allocated memory.
sizeof() will work as you might have expected when using stack arrays. If test is declared as
char test[10][20];
Then sizeof(test) will in fact return 200.
How I can get it's length (=rows)?
You cannot. Read more in How to get the length of dynamically allocated two dimensional arrays in C
Your attempt:
char** foo;
sizeof(foo[0])/sizeof(foo[0][0])
most probably results in 8, right? That's because you are getting the size of a pointer (which is probably 8 in your system) and then divide by the size of a character, which is always 1.
If you are allocating something large you use malloc() and malloc receives one argument - the size in bytes(e.g malloc(sizeof(int)*20).
malloc also returns a void pointer to the allocated memory. You typically cast this pointer to fit your type.
In other words you can't really get the size. You must store it somewhere and pass it to other functions when its needed.
A pointer to pointer (**) is like adding one additional dimension.
[] these are more of a syntax sugar for pointer arithmetic.
a[i] would be the same as *(a+i).
This may vary on your system but sizof() will give you these values for these types.
int a; //4
int b[5]; //20
int* c; //8
int d[5][5];//100
int** e; //8

Non-defined sized array in 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.

I'm very confused about malloc() and calloc() on C

I've always programmed in Java, which is probably why I'm so confused about this:
In Java I declare a pointer:
int[] array
and initialize it or assign it some memory:
int[] array = {0,1,0}
int[] array = new int[3]
Now, in C, it's all so confusing. At first I thought it was as easy as declaring it:
int array[]
and initializing it or assigning it some memory:
int array[] = {0,1,0}
int array[] = malloc(3*sizeof(int))
int array[] = calloc(3,sizeof(int))
Unless I'm wrong, all of the above is equivalent Java-C, right?
Then, today I met a code in which I found the following:
pthread_t tid[MAX_OPS];
and some lines below, without any kind of initialization...
pthread_create(&tid[0],NULL,mou_usuari,(void *) 0);
Surprisingly (at least to me), the code works! At least in Java, that would return a nice "NullPointerException"!
So, in order:
Am I correct with all of the Java-C "translations"?
Why does that code work?
Is there any difference between using malloc(n*sizeof(int)) and calloc(n,sizeof(int))?
Thanks in advance
You can't assign memory to an array. An array has a fixed size, for the whole of its lifespan. An array can never be null. An array is not a pointer.
malloc returns the address to a memory block that is reserved for the program. You can't "assign" that (being the memory block) to an array, but you can store the address of this memory block in a pointer: luckily, array subscription is defined through pointers - so you can "use pointers like arrays", e.g.
int *ptr = malloc(5 * sizeof *ptr);
ptr[2] = 5; // access the third element "of ptr"
free(ptr); // always free at the end
When you declare an array without a size (i.e. array[]), it simply means the size of the array is determined from the initializer list. That is
int array[] = {1, 2, 3, 4, 5}; // is equal to
int array[5] = {1, 2, 3, 4, 5};
Trying to declare an array without a size and without an initializer is an error.
The code pthread_t tid[MAX_OPS]; declares an array named tid of type pthread_t and of size MAX_OPS.
If the array has automatic storage (i.e. declaration is inside a function and not static, not global), then each of the arrays elements has indeterminate value (and it would cause undefined behavior trying to read such value). Luckily, all that the function call does is that it takes the address of the first element of the array as the first parameter, and probably initializes it (the element) inside the function.
The difference of calloc and malloc is that the memory block that calloc returns is initialized to zero. That is;
int *ptr = calloc(5, sizeof *ptr);
// is somewhat equal to
int *ptr = malloc(5 * sizeof *ptr);
memset(ptr, 0, 5 * sizeof *ptr);
The difference between
int *ptr = malloc(5 * sizeof *ptr);
// and
int array[5];
is that array has automatic storage, (is stored on stack), and is "released" after it goes out of scope. ptr, however, (is stored on heap), is dynamically allocated and must be freed by the programmer.
You are missing three very basic and tighten (and misleading!) C topics:
the difference between array and pointers
the difference between static and dynamic allocation
the difference from declaring variables on the stack or on the heap
If you write int array[] = malloc(3*sizeof(int)); you would get a compilation error (something like 'identifier' : array initialization needs curly braces).
This means that declaring an array allows only static initialization:
int array[] = {1,2,3}; that reserves 3 contiguous integers on the stack;
int array[3] = {1,2,3}; which is the same as the previous one;
int array[3]; that still reserves 3 contiguous integers on the stack, but does not initialize them (the content will be random garbage)
int array[4] = {1,2,3}; when the initializer list doesn't initialize all the elements, the rest are set to 0 (C99 §6.7.8/19): in this case you'll get 1,2,3,0
Note that in all these cases you are not allocating new memory, you are just using the memory already committed to the stack. You would run in a problem only if the stack is full (guess it, it would be a stack overflow). For this reason declaring int array[]; would be wrong and meaningless.
To use malloc you have to declare a pointer: int* array.
When you write int* array = malloc(3*sizeof(int)); you are actually doing three operations:
int* array tells the compiler to reserve a pointer on the stack (an integer variable that contains a memory address)
malloc(3*sizeof(int)) allocates on the heap 3 contiguous integers and returns the address of the first one
= assigns copies that return value (the address of the first integer you have allocated) to your pointer variable
So, to come back to your question:
pthread_t tid[MAX_OPS];
is an array on the stack, so it doesn't need to be allocated (if MAX_OPS is, say, 16 then on the stack will be reserved the number of contiguous bytes needed to fit 16 pthread_t). The content of this memory will be garbage (stack variables are not initialized to zero), but pthread_create returns a value in its first parameter (a pointer to a pthread_t variable) and disregards any previous content, so the code is just fine.
C offers static memory allocation as well as dynamic- you can allocate arrays off the stack or in executable memory (managed by the compiler). This is just the same as how in Java, you can allocate an int on the stack or an Integer on the heap. Arrays in C are just like any other stack variable- they go out of scope, etc. In C99 they can also have a variable size, although they cannot be resized.
The main difference between {} and malloc/calloc is that {} arrays are statically allocated (don't need freeing) and automatically initialized for you, whereas malloc/calloc arrays must be freed explicitly and you have to initialize them explicitly. But of course, malloc/calloc arrays don't go out of scope and you can (sometimes) realloc() them.
2 - This array declaration is static :
pthread_t tid[MAX_OPS];
We don't need to allocate memory block, instead of dynamic allocation :
pthread_t *tid = (pthread_t *)malloc( MAX_OPS * sizeof(pthread_t) );
Don't forget to free the memory :
free(tid);
3 - The difference between malloc and calloc is calloc allocate a block of memory for an array and initializes all its bits at 0.
I find it helpful when you are programming in C (as opposed to C++) to indicate *array explicitly, to remember that there is a pointer that can be moved around. So I would like to start by rephrasing your example as:
int array[] = {0,1,2};
int *array = malloc(3*sizeof(int));
int *array = calloc(3,sizeof(int));
The first makes it clear that there is something called array which is pointing to a block of memory that contains a 0, 1 and 2. array can't be moved elesewhere.
Your next code:
pthread_t tid[MAX_OPS];
Does in fact cause an array with sizeof(pthread_t) * MAX_OPS to be allocated. But it does not allocate a pointer called *tid. There is an address of the base of the array, but you can't move it elsewhere.
The ptherad_t type is actually a cover for a pointer. So tid above is actually an array of pointers. And they are all statically allocated but they are not initialized.
The pthread_create takes the location at the beginning of the array (&tid[0]), which is a pointer, and allocates a block of memory to hold the pthread data structure. The pointer is set to point to the new data structure and the data structure is allocated.
Your last question --- the difference between malloc(n*sizeof(int)) and calloc(n,sizeof(int)) is that the later initializes each byte to 0, while the first does not.

Resources