Defining malloc array size with scanf and initialising - c

I'm trying to create a program that asks the user for a size of an array, then asks the user to populate it.
Whenever I launch the program, the "Element %d" printf displays the %d as a large number instead of 1.
If I continue the program after entering the value into the array, the debugger crashes. What's happening here? Did I accidentally place the address in the array position? Thanks
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int elements = 0;
printf("How many Elements will you enter?");
scanf("%d", &elements);
int* elementArray = malloc(sizeof(int) * elements);
int i = 0;
while (elementArray[i] != '\0')
{
printf("Element %d: ", elementArray[i]);
scanf("%d", &elementArray[i]);
i++;
}
free(elementArray);
return 0;
}
EDIT: Reading the comments, I meant printf("Element %d: ", elementArray[i]); was supposed to print one during the first loop. Though I should edit the code to be elementArray[i] + 1 so it doesn't print "Element 0" instead of Element 1. Apologies for the barebones code, it's half finished, I wanted to solve this problem before finishing it off. Will work on the solutions given now. Thanks for the help
EDIT2: Thanks to all of you, especially Sharuya! Here's my finished code.
void printArray(int* elemArray, int elements)
{
printf("The Array contains: ");
for (int k = 0; k < elements; k++)
{
printf("%d,\t", elemArray[k]);
}
}
int main(void)
{
int elements = 0;
printf("How many Elements will you enter?");
scanf("%d", &elements);
int* elementArray = (int *)malloc(sizeof(int) * elements);
int input = 0;
for (int j = 0; j < elements; j++)
{
printf("Element %d: ", j + 1);
scanf("%d\n", &input);
*(elementArray + j) = input;
}
printArray(elementArray, elements);
free(elementArray);
return 0;
}
Only issue now is, between the "Element 1: " and "Element 2: " printf, I get a blank line, that allows me to enter a number, upon submitting, it continues as normal. If I submit an array with 5 elements, It asks me for 6 elements, and only 5 appear... What's happening here?

while (elementArray[i] != '\0')
This check is the problem
malloc gives no guarantee that the memory initialized will be zero filled. Hence your loop may cross over the allocated memory and try to read memory that your program is not supposed to read (hence resulting in a crash)
If it's zero filled your code will never enter the loop
What you need is
while (i < elements)
Also printf should come after scanf for any meaningful result. If you want to just get the index that you are about to enter use printf("Element: %d", i) instead of elementArray[i]

A couple of questions, for you to ask:
What if the user enters a negative value?
What if the user enters 0 ?
What if the user enters a very large value?
Did the array allocation succeed?
What is in my array after it is allocated?
If my array size is 0, will elemenArray[0] be valid?
Should I use a for loop, like everyonbe else does for walking through my array?
Just asking yourself these questions will fix this program in no time, and will get you through half of the next one you'll write.

You have more problems than the fact that you print something else than the index.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int elements = 0;
printf("How many Elements will you enter? ");
if((1!=scanf("%d", &elements))||(elements<1) ) // check return value, always a good idea
{ printf("Reading number failed.\n");
return 1;
}
int* elementArray = malloc(sizeof(int) * elements);
int i = 0;
while ( (i<elements) // use the number you asked for to avoid writing beyond array
&& ((0==i) || (0 != elementArray[i-1]))) // stop when previously entered value is 0
{
printf("Element %d: ", i+1); // print the index
// instead of the non-initialised value
if(1!= scanf("%d", &elementArray[i]))
{
printf("Reading value failed!\n");
free(elementArray); // cleanup
return 1;
}
i++;
}
if (i<elements)
{
printf("Stopped early because 0 was entered.\n");
}
free(elementArray);
return 0;
}

First you need to know that malloc() function dynamically allocates memory according to the size calculated (with the help of sizeof() ) and returns the address of this memory location.
However this address is not associated with any data type i.e. only a void* pointer can store this address of an incomplete data type.
Thus instead of mentioning
int* elementArray = malloc(sizeof(int) * elements);
mention and use typecasting to it
int* elementArray = (int *)malloc(sizeof(int) * elements);
As per your code, elementArray is a pointer which will store the address of an integer
int *elementArray;
printf("Element %d: ", elementArray[i]);
Thus the above line will actually print the address pointed to by the pointer and not the index since incrementing a pointer is same as
elementArray stores the base address.
i.e elementArray++ is equal to elementArray+1 == elementArray[1] will point
to the next memory location after 4 bytes.(since integer is stored in 4 bytes)
I have modified your code correcting your mistakes
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int elements = 0;
printf("How many Elements will you enter?");
scanf("%d", &elements);
//the below statement actually allocates contiguous block of memory equal
//to no of elements and the pointer points only to first element.
//Incrementing it will point to next element
int* elementArray =(int *) malloc(sizeof(int) * elements);
//typecasting of void* pointer to int*
int i = 0,elm;
for(i=0;i<elements;i++)
//Since u know iterations will be equal to no of elements it is better to use for loop
{
printf("Element %d: ", i);
scanf("%d", &elm);
*(elementArray+i)=elm;
//Storing the data in elm and making the pointer point to next free
//dynamically allocated block of memory and using * operator the value at
//this location is accessed and storing elm value in it
}
for(i=0;i<elements;i++)
printf("%d",*(elementArray+i));
free(elementArray);
return 0;
}
This code works and I hope it make things clear !!!

Related

invalid pointer in realloc

This error never appeared before, I don't understand why it is happening. I am creating a C program to create an array and then realloc it to add more elements. Im applying many unecessary concepts in the same program to condense some knowledge.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// ALWAYS when doing a definition of new elements in a arrays, NEVER use size as a parameter
// because if you assign one element as one, it will reset the value of size then reseting
// size < sizenew.
// Ex: Do not do:
//
// for (size; size < newsize; size++) scanf ("%hu", &size)
//
// the number you choose for scanf will affect the number of times the loop will do, because size
// is a parameter of while
int main()
{
_Bool decision;
int* array;
unsigned short size, newelements, oldsize, add, minus_oldsize, newsize, i, j;
printf("Hello! put the size of the initial int array!\n");
scanf("%hu", &size);
array = malloc(size * 4);
printf("Put the array elements one by one\n");
for (i = 0; i < size; i++) scanf("%d", array + i);
printf("This is your array:\n");
for (j = 0; j < size; j++) printf("%d\n", *(array + j));
printf("Do you want to add more elements? no(0) yes(1)\n");
scanf("%d", &decision);
if (decision != 1) return -1;
printf("How many elements you want to add?\n");
scanf("%d", &newelements);
newsize = size + newelements;
array = realloc(array, newsize * 4);
free(array);
return 0;
}
error:
realloc(): invalid pointer
It seems the problem is this call of scanf for an object of the type _Bool
_Bool decision;
//...
scanf("%d", &decision);
Unfortunately there is no conversion specifier for objects of the type _Bool that can be safely used in a call of scanf.
Instead you could use an object of the type int.
Another problem is using an incorrect conversion specifier in this call
scanf("%d", &newelements);
It seems you mean
scanf("%hu", &newelements);

What does int i do inside of the for loop(in scanf and sum) in this particular program?

Isn't i in scanf and in sum useless? It doesn't change anything, even when I print &ptr it doesn't show me any difference in memory values.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
ptr = (int *)malloc(n * sizeof(int));
// if memory cannot be allocated
if (ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}
printf("Enter elements: ");
for (int i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum = sum + *(ptr + i);
}
printf("Sum = %d", sum);
// deallocating the memory
free(ptr);
return 0;
}
The 'i' isn't supposed to change the pointer. It is used to access the i'th element of the array that PTR points to. Without the I it would scan for the same element in this array, the first element
If you don't use 'i' in both sum and scanf, there won't be any effect on sum because it will take input in the first index of the dynamic memory and overwrite it. This 'i' is helping to store inputs in the dynamic memory.
'i' isn't a useless value, it is used to offset the pointer to access the correct element of the dynamic array.
It is the same as using
for (int i = 0; i < n; ++i) {
scanf("%d", &ptr[i]);
sum = sum + ptr[i];
}
The purpose of the index i in the for is twofold:
ensure n numbers are read and cumulated in sum.
store each converted number into a separate entry in the array pointed to by ptr.
Given what the program does, it is not required to store the numbers into an array, or even necessary to allocate this array.
Here is a simpler version:
#include <stdio.h>
int main() {
int n, v, sum = 0;
printf("Enter number of elements: ");
if (scanf("%d", &n) != 1)
return 1;
printf("Enter elements: ");
for (int i = 0; i < n; i++) {
if (scanf("%d", &v) != 1) {
printf("input error\n");
break;
}
sum = sum + v;
}
printf("Sum = %d\n", sum);
return 0;
}
"What does int i do inside of the for loop?"
i is used for the pointer offset to access subsequent int objects of the dynamically allocated memory.
It works as:
(value of ptr [address of pointed object by ptr] + (i * sizeof(pointed object by ptr))).
Maybe take a look at this Stack Overflow question.
Note: The purpose is just to dereference and modify pointed to objects, not the pointer itself. ptr won´t get changed because of this pointer arithmetics.
"It doesn't change anything, even when I print &ptr it doesn't show me any difference in memory values."
Probably it doesn´t show different values because you print the address of the pointer itself, which doesn´t change by using offsets to the pointer.
I say "probably" because I don´t see how you actually print the address of ptr in particular. Maybe you even have some kind of kind of undefined behavior.

How to properly free dynamically allocated memory for an array of pointers to int's

I need to know if I have used free() correctly while attempting to free dynamically allocated memory for an array of pointers to int's.
My code is modified from a code snippet out of one of my books and is the beginning of a program which requests temperature readings for three cities.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ctr, num, num2 = 0, ctr2 = 0;
int* temps[3];
for(ctr = 0; ctr < 3; ctr++)
{
puts("how many readings for the city?");
scanf(" %d", &num);
temps[ctr] = (int*)malloc(num * sizeof(int));
num2 += num;
while(ctr2 < num2)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
}
for(ctr = 0; ctr < 3; ctr++)
{
free(temps[ctr]);
}
getchar();
getchar();
return (0);
}
I know that a pointer which is assigned memory using malloc() may have values assigned and accessed through a combination of a loop and array indexes. Hence I have assigned values from user input using the indexes of a two dimensional array, and need to know if I used free correctly. I know this is extremely sloppy coding and I am merely seeking to understand free correctly to prevent any potential memory leaks.
it's okay since you respect the same number of loops for allocation and deallocation with the same statement:
for(ctr = 0; ctr < 3; ctr++)
Just make sure that temps can hold at least 3 elements, which is the case, and that num is not zero or undefined (test return value of scanf & value of num). You can use a sizeof formula in your case to avoid hardcoding the value, only because you have an array of pointers, not pointers on pointers.
also avoid casting return value of malloc. And use the size of the element, instead of hardcoding as int (so if type of the pointer changes, your sizes are still right). Improvement suggestion for allocation:
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
puts("how many readings for the city?");
if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); } // or better error handling
temps[ctr] = malloc(num * sizeof(*temps[ctr]));
You may still get a segmentation fault when calling free if you corrupt the memory when filling your arrays (a comment suggests it does, since num2 grows and grows). If you get such errors, run your code with valgrind, or just perform allocations/deallocations (and not the rest) to find which part of the code causes the problem.
The proper way of freeing the dynamically allocated memory is to free it after you check if it has been allocated at the very first place or not. As your loop structure is same for allocating and freeing, there wont be any problem here as such if all the allocations are successful. Therefore I suggest you check at all the places if the allocation is successful after allocating and also check if the memory is allocated before freeing.
Following code will make sure all the cases:
scanf(" %d", &num);
/*
* check here if the value of ctr in non-negative and in the appropriate range
*/
temps[ctr] = (int*)malloc(num * sizeof(int));
if (temps[ctr] == NULL) {
printf ("Memory allocation failed\n");
/*
* appropriate error handling
*/
}
Also, check when you are freeing the memory to be on the safer side.
for(ctr = 0; ctr < 3; ctr++)
{
if(temps[ctr]) {
free(temps[ctr]);
}
}
Also there is a bug in your code where after the first iteration itself you will get memory out of bound error, as the variable ctr2 in never reinitialized.
num2 += num;
while(ctr2 < num2)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
Here if the value of num was 20 in the first iteration, then in the second iteration you will end up taking the input starting from temps[1][20], and assuming the value of num in the second iteration to be 5, you have allocated just 5 * sizeof(int)), so obviously you are going out of bounds when you try to access temps[1][20].
Please let me know if the following code would be considered acceptable:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ctr, num, ctr2 = 0;
int * temps[3];
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
puts("how many readings for the city?");
if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); }
temps[ctr] = (int *) malloc(num * sizeof(*temps[ctr]));
while(ctr2 < num)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
ctr2 = 0;
}
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
free(temps[ctr]);
}
getchar();
getchar();
return (0);
}

Unwanted Output in C Program

I have a class project to make an array, declare it's size (add 1) then fill it in numerical, nondecreasing order. After that, I need to declare x, a value to be added to the array in the appropriate spot, so the array is still nondecreasing.
The program builds without error (for once!) but I'm getting some really weird outputs.
#include <stdio.h>
int main (void) {
//Local Declarations
int size;
int ary[100];
int x;
int i;
int j;
//Statements
printf("Enter the size of the array: ");
scanf("%d", &size);
printf("\nEnter digits to fill the array, in numerical order: ");
for (i = 0; i < size; i++) scanf("%d", &ary[i]);
size++;
printf("\nInput x, the value to add to the array: ");
scanf("%d", &x);
while(i <= x && x > ary[i]){
i++;
j = size - 1;
while(j >= i) {
ary[j++] = ary[j];
j--;
}
}
for(i = 1; i < size; i++) {
printf("%d", &ary[i]);
}
return 0;
} //main
When it runs I get:
Enter the size of the array: 3
Enter digits to fill the array, in numerical order: 1
2
3
Input x, the value to add to the array: 4
268634426863482686352
Process returned 0 (0x0) execution time : 7.124 s
Press any key to continue.
I would examine your print function . It looks like you're printing the memory address of that particular array index rather than the value at that spot in the array.
Don't increase the size variable before you iterate through. Then walk backwards through the array, and populate as needed.
for (i = size; i >0; --i)
{
if (ary[i-1] > x)
{
ary[i] = ary[i-1];
}
else
{
ary[i] = x;
break;
}
}
if (i == 0)
ary[i] = x;
Afterwards, you can increase size as you print the output.
I've reproduced your desired output using this array walk.
There are other ways that I would solve this problem in real life, but this works well enough within your existing code.
First things first: what do you EXPECT to see as the output?
Second things first: you aren't clearing out the memory for the array before use. You have garbage values in any slots you aren't using.
Third things first: using GCC I'm seeing at least two warnings without even trying.
test.c:32:15: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%d", &ary[i]);
test.c:27:14: warning: unsequenced modification and access to 'j' [-Wunsequenced]
ary[j++] = ary[j];
In your printing loop your are not printing the value but your are printing the address of that element. Change the last loop to
for(i = 1; i < size; i++) {
printf("%d", ary[i]);
}
I am not sure why your are printing the array from index 1. But if you want to print whole array you should initialize i to zero in above loop.

a C program crashes, using a double-type variable length array

I am reading C Primer Plus these days and here is the code I wrote for the programming practice No.4 in Chapter 10, finding the index of the largest number in a double-typed array. I used variable length array in order to manually specify the array size:
#include <stdio.h>
int findmax(const double array[], int s);
//find the index of the largest number in the array
int main(void)
{
int size = 0; //size of the array
int index = 0; //index of the largest number
double num[size]; //the array holding double-type numbers
printf("Enter the size of the array: ");
scanf("%d", &size);
printf("Enter %d numbers: ", size);
for (int i = 0; i < size; i++)
scanf("%lf", &num[i]);
index = findmax(num, size);
printf("The index of the max number in the array is: %d\n", index);
return 0;
}
int findmax(const double array[], int s)
{
int index = 0;
double max = array[0];
for (int i = 0; i < s; i++)
if (array[i] > max)
{
max = array[i];
index = i;
}
return index;
}
This piece of program compiles normally, using MinGW (assume the program file name is prog.c):
gcc prog.c -o prog.exe -std=c99
The program works fine when the "size" varialbe is less than 5. But when I enter 6 or larger numbers for the "size" varialbe, the program crashes during runtime.
Loosely translated, the error message is:
the memory 0x00000038 used by 0x77c1c192 could not be "written".
I tried to eliminate the use of variable length array, the program seems to work fine. But I still couldn't get where is wrong with the original one.
Size is 0 when you allocate num. You get access violation later on because you try to acces num[0] which has not been allocated.
EDIT: I propose to use dynamic memory or declare num after size is read.
Put the statment double num[size]; after taking input of size from user for size variable.
The program works fine when the "size" varialbe is less than 5. This is the most dangerous kind of programming error -- one that appears to work fine but really does not. By writing into your array, you're immediately writing into memory that is claimed for some other purpose, because your array has no length at all. You cannot just change the size of your array by changing the size variable after the fact.
One option is to determine size before you declare the array. Another is to perform a dynamic allocation using new, but you'll get into that in several chapters, I'm sure.
int size = 0; //size of the array
int index = 0; //index of the largest number
double num[size]; //the array holding double-type numbers
printf("Enter the size of the array: ");
scanf("%d", &size);
When you first declare num array, it's size would be zero, as this is the value of size when that line is executed, although you maybe reading the value of size again later on.
When you are creating an array, the size of the array will be zero as already pointed out by others. So, when you try to fill elements into the array, there is no memory available and it overwrites into some other memory eventually leading to a memory corruption.
You can rewrite the code as below to avoid the problem.
int size = 0; //size of the array
int index = 0; //index of the largest number
double *num = NULL; //Change it to a pointer
printf("Enter the size of the array: ");
scanf("%d", &size);
num = malloc(size * sizeof(double));
if(NULL == num)
{
printf("Malloc Failed\n");
return 0;
}
printf("Enter %d numbers: ", size);
for (int i = 0; i < size; i++)
scanf("%lf", &num[i]);
or
int size = 0; //size of the array
int index = 0; //index of the largest number
printf("Enter the size of the array: ");
scanf("%d", &size);
double num[size]; //Now, num will have proper size
printf("Enter %d numbers: ", size);
for (int i = 0; i < size; i++)
scanf("%lf", &num[i]);
Here's a link to an informative article about C99's variable length arrays which talks about some potential problems which C99's variable length arrays can cause.
As others have suggested, using malloc() is the correct way to do this. Other than that, you can just make your array an arbitrary large size, and stop accepting input once it's full.

Resources