I'm attempting to load an array of size n (user input), with random values. I've read that you can not return an array in C, you must use a pointer (Which is quite confusing). However, I've read that if you are storing that array to a local variable in the returning function, a pointer will not work and a static array can be used (can that be returned in a function?). Also, I've read that you are supposed to call free after using the array is open the space back up? I must be using it wrong because it crashed. So I commented it out for now. Some clarification would be great.
Here's what I have so far. When printing, it's just printing what I'm assuming is just garbage.
int* prefixAverages1(int);
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main() {
int choice;
int input;
printf("What is the size of the array?:");
scanf("%d", &input);
printf("Do you want to run prefixAverages 1 or 2?");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("Beginning prefixAverages1\n");
int *a = prefixAverages1(input);
for (int i=0; i < input; i++) {
printf("%d", &i);
printf("%d \n", a[i]);
}
//free(a);
break;
}
}
int* prefixAverages1(int input) {
int x[input];
int *a = (int*)malloc(input);
srand(time(NULL));
for(int i = 0; i < input; i++) {
int s = 0;
for(int j = 0; j < i; j++) {
int r = rand() % 100;
x[j] = r;
s = s + x[j];
}
a[i] = s / (i+1);
printf("%d \n", a[i]);
}
return a;
}
I'm aware my syntax may be wonky. I haven't touched C in years, so let me know if my error is syntaxical.
edit: Values are printing as intended in the function. Added print statement in code for clairity
I'm attempting to load an array of size n (user input), with random
values. I've read that you can not return an array in C, you must use
a pointer (Which is quite confusing).
Yes, the relationship between pointers and arrays and the surprisingly wide scope of things you cannot do with arrays themselves are common points of confusion. To some extent it's a pedantic distinction. Almost everything C allows you to do with an array, it makes you do via a pointer, but it automatically converts values of array type to appropriate pointers, so that those details are largely hidden.
But in some places it pokes out. For example, there is no valid syntax that allows you even to try to declare a function that returns an array.
In other places it is actively misleading. For example, you can declare a function that appears to accept an array as an argument, but the standard explicitly specifies that the argument is actually a corresponding pointer (and that's what naturally falls out when you call such a function anyway). Specifically:
int foo(int x[3]);
is 100% equivalent to
int foo(int *x);
However, I've read that if you
are storing that array to a local variable in the returning function,
a pointer will not work
That's not so much about arrays specifically, but rather about automatic variables in general. These logically cease to exist when they go out of scope -- at the end of the innermost block in which they are declared -- so pointers to or into such objects are no longer valid once the function returns. One way to obtain such a pointer value is for the function to return it. That in itself is OK, but you cannot safely dereference such a pointer value.
and a static array can be used (can that be
returned in a function?).
The lifetime of static variables of any type is the whole execution of the program. Therefore, it is safe and can be meaningful to return a pointer (in)to a static variable from a function. But although it can work to return a pointer to a static array from your function, you still cannot return such an array itself.
Also, I've read that you are supposed to
call free after using the array is open the space back up?
You should free memory that you have allocated with one of the memory allocation functions (malloc() etc.), and no other. But when you allocate memory inside a function, you can give the caller responsibility for freeing that memory by returning the pointer to it, among other ways.
In fact, most of what you demonstrate in your example code is fine in those regards. However, you do make a key error that undermines your program. Here:
int *a = (int*)malloc(input);
You allocate input bytes and store the pointer to them in a, but that is not enough storage for input objects of type int. The size of an int varies from implementation to implementation, but the minimum size permitted by the standard is two bytes, in the most common size is four bytes. To allocate space for input objects of type int, the basic idiom is
int *a = malloc(input * sizeof(int));
Personally, though, I prefer
int *a = malloc(input * sizeof(*a));
because then I get the correct size no matter what type the pointer's referenced type is, and even if I change it later.
The fact that you treated the allocated space as if it were larger than it really was likely explains much of your program's misbehavior, including the crash when you tried to free the allocated memory.
First of all malloc takes an inparam of no of bytes not absolute array size - so change this line:-
int *a = (int*)malloc(input);
to
int *a = malloc(input*sizeof(int));
Secondly, to debug incorrect values being printed put a print in your function prefixAverages1 :-
...
...
a[i] = s / (i+1);
printf("%d \n", a[i]);
...
In main print, get rid of the first print.. this is probably making you think printing incorrect values.. The address of the local loop counter variable will look like garbage
printf("%d", &i);
OR if you wanted to track the indexes of the array elements as well modify it to :-
printf("%d", i);
You must introduce the free back to avoid leaking memory
And you should follow #AustinStephens's suggestion and avoid using a second function
This works as far as having a function that loads an array with random values:
void randomValues(int arr[], int size);
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main() {
int i;
int input;
int *array;
printf("What is the size of the array?: ");
scanf("%d", &input);
array = malloc(sizeof(int) * input);
randomValues(array, input);
for(i = 0; i < input; ++i)
printf("array[%d] = %d\n", i, array[i]);
free(array);
return 0;
}
void randomValues(int arr[], int size) {
int i;
int r;
srand((int) time(0));
for(i = 0; i < size; ++i) {
r = rand() % 100;
arr[i] = r;
}
}
Related
I don't understand where the error is in the function.I need to print 2 arrays with random elements.
int *boo3(int *x , int n){
x = (int*) malloc(sizeof(int)*n);
int i;
for(i=0;i<n;i++){
x[i] = rand()%10-(rand()%10);;
printf("%5d ",x[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
int *x ,*y;
int n , m;
int i,j;
printf("enter size of X[n]: ");
scanf("%d",&n);
printf("enter size of Y[m]: ");
scanf("%d",&m);
x=boo3(*x,n);
y=boo3(*y,m);
free(x);
free(y);
return 0;
}
There are several problems with this code:
x = (int*) malloc(sizeof(int)*n); overwrites the function parameter x.
No return statement in boo3,
x=boo3(*x,m) in this line, *x is dereferencing pointer x which gives you int
In main function, you tried to free uninitialized pointer x and y
In your code
int *boo3(int *x , int n)
This indicates that you should receive a return value from this function.
In general a return value can be error code or any data which you might want to use going ahead.
Just like a math function for addition, taking operands as an argument and returning the sum. In your case, it is a pointer to the memory you have been allocated with.
In boo3() function, you are allocating some memory and you need the pointer to that memory for further usage. boo3() doesn't return anything, however, in main() function, you are assuming that you have caught it, hence the problem.
You should return the pointer to data from boo3().
I can see in main() function,
x=boo3(*x,n);
This is alarming. You are dereferencing a int* pointer and passing an int (instead of int*) as an argument to boo3() function which expects a int*.
If you wish to assign the pointer declared in main() with the address of memory allocated in boo3(), then you don't catch it and change to
boo3(x, n);
boo3(y, m);
And change to
void boo3(int *x , int n)
However, ideally, the function should return and the value be caught as a return value. In that case, change to
int* boo3(int n)
At the end of boo3 add a return x;. And use it as
x = boo3(n);
Additionally, you are not checking if the malloc() has allocated any memory or not. You should check if the pointer is NULL to see if memory is allocated. It is minimum error-checking and handling you need to have. Secondly, malloc() returns a void*, so the typecast is needless.
The problem is, you do not return anything from the function boo3(), and try to use the return value. This causes undefined behavior.
You need to add a return x; at the end of the function so as to return the pointer holding the address of the allocated memory (and populated values).
That said, passing the pointer argument is not needed when you return the pointer from the function. Apart from the fact that your call does not even try to pass a pointer as the first argument, as expected by the function signature - to allocate memory to a pointer from a called function, you need to pass the address of the pointer anyways, passing the pointer alone will not suffice. You don't need to do that, just define the function as
int *boo3(int n) { //......
and in the end, add
return x;
and from main(), call it like
x=boo3(n);
y=boo3(m);
There are many issues in your code.
Following has been corrected:
boo3 now simply returns the pointer to the allocated memory filled with random numbers, the useless x parameter has been removed and the function now contains the missing return statement. This is actually the main problem in your code.
The pointless (int*) cast has been removed from malloc.
The code is formatted properly.
Variables are declared as close as possible to their scope. This is the idiomatic way, declaring all variables at the start of the scope is a thing from the last century.
Usage of meaningful variable names.
This is a correct version of your program:
#include <stdlib.h>
#include <stdio.h>
int* boo3(int n) {
int *array = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
array[i] = rand() % 10 - (rand() % 10);;
printf("%5d ", array[i]);
}
printf("\n");
return array;
}
int main(int argc, char* argv[])
{
int sizex, sizey;
printf("enter size of X[n]: ");
scanf("%d", &sizex);
printf("enter size of Y[m]: ");
scanf("%d", &sizey);
int *xvalues = boo3(sizex);
int *yvalues = boo3(sizey);
free(xvalues);
free(yvalues);
return 0;
}
Disclaimer: for brevity there is no error checking for scanf and malloc.
This question already has answers here:
printf() no format string printing character and integer arrays --> garbage
(3 answers)
Closed 2 years ago.
I am having a crazy output with funny characters (Φw ÅΩw) can i know what's wrong in the code?
probably the int main is wrong
i am obliged with int sumArray (int * a, int len , int * sum )format
#include <stdio.h>
#include <stdlib.h>
int sumArray(int *a, int len, int *sum) {
int sum1 = 0;
if (a == NULL || sum == NULL)
return -1;
int i;
(*sum) = 0;
for (i = 0; i < len; i++) {
(*sum) += a[i];
}
return 0;
}
int main() {
int *a = {1, 2, 3, 4};
int *b;
sumArray(&a, 4, &b);
printf(b);
return 0;
}
Can you try these changes ?
#include <stdio.h>
#include <stdlib.h>
int sumArray(int *a, int len, int *sum) {
// int sum1 = 0; // i removed this variable because you are not using it
if (a == NULL || sum == NULL)
return -1;
int i;
(*sum) = 0;
for (i = 0; i < len; i++) {
(*sum) += a[i];
}
return 0;
}
int main() {
// int *a = {1, 2, 3, 4};
int a[] = {1, 2, 3, 4};
int b;
// i rather declare an integer instead of a pointer to an integer
// when you declared int * b , this was a pointer, and your printf(b) was
// printing an address, not the value calculated by sumArray that is why you
// were printing funny characters
sumArray(a, 4, &b);
// a is already a pointer
printf("%d", b);
return 0;
}
You are using your pointers uninitialized. When you create a pointer, you don't know where the pointer points to. It either will be pointing to some garbage data, or in worse case, it will be pointing to a memory region which is already being used by some other program in your computer or maybe by OS itself.
If you really want to use pointers like this, you should dynamically allocate memory for them.
int* a = malloc( 4 * sizeof(int) );
int* b = malloc( sizeof(int) );
This makes sure that you can assign four integers to the memory region to which a points to. And one for b.
You then can wander in that memory using loops to assign, read or write data.
for ( int i=0; i < 4; i++ )
{
*(a + i) = i + 1;
}
Here we have a for loop which will run 4 times. Each time we are moving one block in the memory and putting the number we want there.
Remember, a is a pointer, it points to the beginning of a 4 int sized memory region. So in order to get to the next block, we are offsetting our scope with i. Each time the loop runs, a + i points to the "ith element of an array". We are dereferencing that region and assigning the value we want there.
for ( int i=0; i < 4; i++ )
{
printf("%d\n", *(a + i) );
}
And here we are using the same logic but to read data we just write.
Remember, you need to use format specifiers with printf function in order to make it work properly. printf() just reads the whatever data you happened to give it, and format specifier helps interpret that data in given format.
If you have a variable like int c = 65; when you use %d format specifier in the printf you will read the number 65. If you have %c specifier in the printf, you will read letter A, whose ASCII code happens to be 65. The data is the same, but you interpret it differently with format specifiers.
Now, your function int sumArray(int *a, int len, int *sum) accepts int pointer for the first argument. In the main function you do have an int pointer named a. But you are passing the address of a, which results in double indirection, you are passing the address of a pointer which holds address of an int array. This is not what you want, so & operator in the function call is excess. Same with b.
Call to the sumArray should look like
sumArray( a, 4, b );
And lastly, we should fix printf as well. Remember what I said about format specifiers.
And remember that b is not an int, it's int*, so if you want to get the value which b points to, you need to dereference it.
In the end, call to printf should look like
printf( "%d", *b );
Also, you should remember to free the memory that you dynamically allocated with malloc. When you use regular arrays or variables, your compiler deals with these stuff itself. But if you dynamically allocate memory, you must deallocate that memory using free whenever you are done with those pointers.
You can free a after the call to sumArray and b before terminating the main function like
free(a); and free(b);
In these kind of small projects freeing memory is probably won't cause any unwanted results, but this is a very very important subject about pointers and should be implemented properly in order to settle the better understanding of pointers and better programming practice.
In that form, your code should work as you intended.
BUT... And this is a big but
As you can see, to make such a simple task, we spent way more effort than optimal. Unless your goal is learning pointers, there is no reason to use pointers and dynamic allocation here. You could have used regular arrays as #Hayfa demonstrated above, and free yourself from a lot of trouble.
Using pointers and dynamic memory is a powerful tool, but it comes with dangers. You are playing with actual physical memory of your computer. Compilers nowadays won't let you to screw your OS while you are trying to add two numbers together but it still can result in hard to detect crashes especially in complex programs.
(Sorry if it's hard to read, I am not necessarily confident with text editor of Stack Overflow.)
I wrote a simple code to create an array of pointers to integer and then fill it with scanf while I was using k&R book to do such things this time I tried to use malloc function but encountered a weird problem
here is the code:
#include<stdio.h>
#include<stdlib.h>
#pragma warning(disable:4996)
int getArr(int **myArr);
void print(int *myArr, int n);
int main() {
int *myArr, n;
n = getArr(&myArr);
print(myArr, n);
return 0;
}
int getArr(int **myArr) {
int n;
scanf("%d", &n);
*myArr = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
scanf("%d", myArr+i); /* here if i put &(*myArr)[i] will work correctly */
return n;
}
void print(int *myArr, int n) {
while (n-- != 0) {
printf("%d\t", *myArr);
myArr += 1;
}
return;
}
but what is the difference between this two types of reading input?
The %d format specifier to scanf expects a int *.
The expression myArr+i has type int ** which doesn't match what is expected, while &(*myArr)[i] (or alternately *myArr+i) has the correct type int *.
since you need the value of the pointer to be updated out of the procedure you rightfully did:
*myArr = (int *)malloc(n * sizeof(int));
(except that you shouldn't cast the return value of malloc in C)
But after that *myArr is the pointer to scan from. myArr is a pointer on the pointer. So you need to keep dereferencing myArr
scanf("%d", (*myArr)+i);
The problem is in getArr() function as myArr is double pointer & while scanning data you should use (*myArr) + i) instead of just myArr + i. Also myArr is not initialized in main() function.
Here is the modified one
int getArr(int **myArr) {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
myArr[i] = malloc(sizeof(int));/*allocate memroy here */
scanf("%d", (*myArr) + i);
}
return n;
}
Your code:
int getArr(int **myArr) {
int n;
scanf("%d", &n);
*myArr = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
scanf("%d", myArr+i); /* here if i put &(*myArr)[i] will work correctly */
return n;
}
Your memory layout looks something like this:
myArr (a pointer who lives on the stack in main()
|
| (points to)
V
[XXXX XXXX XXXX XXXX] (allocated by malloc)
The 4 X's together represent an integer, so this is an array of some sequence of them. When you dereference myArr, you get the pointer to the beginning of the array. When you index THAT pointer, you get elements in the array.
Your code is not doing that:
myArr+i
This is treating myArr as a pointer to array, not a pointer to a pointer. When you provide myArr + i, you're effectively doing this:
myArr --------------------> [WRITE HERE]
|
|
V
[XXXX XXXX XXXX XXXX]
(Imagine memory goes left to right, row by row, so that the array is "far" from myArr, and [WRITE HERE] is closer to it. By adding to the myArr pointer, you're moving into invalid memory areas. myArr literally holds an address in main (since that's where you originally declared it, and passed its address to this function.) When you add to it, you are computing an address somewhere in the main stack frame, and scanf treats it as a pointer to an int, and scribbles some bytes somewhere into your stack.
Your alternate syntax is doing something different:
&(*myArr)[i]
This dereferences myArr, fetching the beginning of your malloc'd array, then indexes into the array for the i'th offset int, then takes the address of that int and passes it to scanf.
The reason this works this way is that [] has higher precedence than &, and so it's equivalent to this:
&((*myArr)[i])
This is the correct way to access your memory given this scheme.
It is good to learn this, but the days of K&R C-style coding are fading, especially in c++ code bases, as the danger and error-prone nature of working with raw pointers like this (as you've discovered) have fortunately been superseded by c++ idioms to help encapsulate memory access and reduce hard to comprehend bugs.
I'm new to using c and I'm trying to make a program that makes an array using pointers,
#include <stdio.h>
int main()
{
int *i;
scanf("%d",i);i++;
while(1){
scanf("%d",i);
if(*i==*(i-1)){
break;}
printf("%d\n",*i);
i++;
}
return 0;
}
I Keep getting this error
Command failed: ./a.out
Segmentation fault
I think you want to create an array and read data to it and later display it using pointers dynamically.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *A, n;
printf("\n Enter the size of array : "); // Reading the size of array
scanf("%d",&n);
A = (int*) malloc(sizeof(int) * n); // Allocating memory for array
int i = 0;
for(i = 0; i < n; i++) // Reading data to array
scanf("%d", (A+i));
// Operations on array
for(i = 0; i < n; i++) // Printing array
printf("%d ", A[i]);
return 0;
}
Hope this help.!!
just a bit of explanation here.
You are declaring your i variable as a pointer here:
int *i;
The pointer does not point anywhere and contains a random value. The following operation tries to write an integer in the memory pointed by the pointer. Since it points to an undefined location, the result of this operation is unpredictable. It can crash, or can write in a place of memory which could create unexpected behavior later, or just work. In any case it causes memory corruption.
scanf("%d",i);i++;
The i++ statement actually increases the value of the pointer so that it points to the next place in memory, which would also be invalid. And so on.
Depending on the purpose of your program you can work around this issue in multiple ways. i.e. if you need just a single integer to work with , you can do the following:
int i;
scanf("%d", &i); // use an address of 'i' here
...
printf("%d", i);
now you can use the 'i' in normal arithmetic operations then. Or if you need an array of integers, you can do the followig:
int i = 0;
int a[mysize];
scanf("%d", &a[i]);
i++; // do not forget to check 'i' against 'mysize'
...
printf("%d", a[i]);
or have 'i' as a pointer:
int a[mysize];
int *i = a;
scanf("%d", i);
i++; // do not forget to check 'i' against 'mysize'
...
printf("%d", *i);
or even have the array allocated in memory by malloc, as this:
int *a = malloc(sizeof(int) * mysize);
int *i = a;
scanf("%d", i);
i++;
...
printf("%d", *i);
Note, that at some point you would need to free the memory in the last example. So, you'd better keep the pointer to the beginning of the array to be able to do free(a);
edits prefixed with ##
after cleaning up the code formatting:
to consistently indent the code
so it follows the axiom: only one statement per line and (at most) one variable declaration per statement.
Then it is obvious that the code contains undefined behavior. (see the ## comments in the code)
## each of the statements containing undefined behavior can cause a seg fault event.
#include <stdio.h>
int main( void )
{
int *i; ## uninitialized pointer declared
scanf("%d",i); ## accessing random memory I.E. undefined behavior
i++;
while(1)
{
scanf("%d",i); ## accessing random memory I.E. undefined behavior
if(*i==*(i-1)) ## reads two consecutive integers using uninitialized pointer I.E. undefined behavior
{
break;
}
printf("%d\n",*i); ## reads integer from memory using uninitialized pointer I.E. undefined behavior
i++;
}
return 0;
}
The undefined behavior, from accessing of memory that the program does not own, is why the seg fault event occurs.
I want to scan a 2D array with the help of pointers and have written this code, could you tell me why the compiler gives errors?
#include<stdio.h>
#include<stdlib.h>
int main(void) {
int i,j,n,a,b;
int (*(*p)[])[];
printf("\n\tEnter the size of the matrix in the form aXb\t\n");
scanf("%dX%d",&a,&b);
p=(int (*(*p)[b])[a])malloc(b*sizeof(int (*p)[a]));
for(i=0;i<b;i++) {
p[i]=(int (*p)[a])malloc(a*sizeof(int));
printf("\t\bEnter Column %d\t\n");
for(j=0;j<a;j++)
scanf("%d",&p[i][j]);
}
return 0;
}
This statement has several problems:
p=(int (*(*p)[b])[a])malloc(b*sizeof(int (*p)[a]));
First, malloc returns a void*. You are casting that pointer using (int (*(*p)[b])[a]) which yields a value, not a data type. That isn't a valid cast, so that's one reason that the compiler is yelling at you. At this point, p hasn't been initialized so the de-referencing taking place here can crash your program if this statement was executed.
Inside your malloc call, you are using sizeof(int (*p)[a]). The statement int (*p)[a] isn't a valid C statement.
It seems that you are making this a bit more complex that it needs to be. There are two ways of building a 2D array. You can build an array using malloc(a * b * sizeof(int)) as Reinderien explains. You can also build a 1D array of pointers, each pointing to an array of type int. From your code, it seems you are trying to do the latter.
The easier way to do this would be something like this:
int **p;
... get input from user ...
// Declare an array of int pointers of length b
p = malloc(b * sizeof(int*));
// For each int* in 'p' ...
for (i = 0; i < b; ++i) {
// ... allocate an int array of length 'a' and store a pointer in 'p[i]' ..
p[i] = malloc(a * sizeof(int));
// ... and fill in that array using data from the user
printf("\t\bEnter Column %d\t\n");
for(j = 0; j < a; j++)
scanf("%d", &p[i][j]);
}
Using this method of building a 2D array allows you to use the syntax p[x][y]. Since p is a pointer-to-pointer, p[x] is a pointer to an array and p[x][y] is an item in the pointed-to array.
That's some pretty contorted syntax. Usually when you make a 2D array:
The declaration is simply int *p;
The allocation is simply p = malloc(a*b*sizeof(int));
You cannot write p[i][j]. You must do one of several things - either make a secondary array int **q that contains row pointers to be able to write q[i][j] (better performance and legibility), or write p[b*i + j] (fewer steps).
Additionally, note that:
Your printf will spew garbage due to the missing %d parameter.
Since C is not typesafe, using scanf will hide any errors in indirection that you may make.
About the closest thing I could think of that remotely resembles what you were trying to do:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j;
const int a = 3, b = 4;
int m[4][3];
int (*p[4])[3];
for (i = 0; i < b; i++)
{
p[i] = &m[i];
printf("\t\bEnter Column %d\t\n", i);
for (j = 0; j < a; j++)
{
int x;
scanf("%d", &x);
(*p[i])[j] = x;
}
}
return 0;
}
It compiles and functions as expected, but it's pointlessly complicated. p is an array of pointers to arrays.