This is C language. When I run my following program, no matter how small values I give, I get runtime segmentation fault error. Please help me find out the cause of this.
#include <stdio.h>
#include <stdlib.h>
struct date
{
unsigned day:
5;
unsigned month:
4;
unsigned year:
12;
};
struct emp
{
char name[10];
struct date d;
};
int compare(const void * a, const void * b)
{
struct emp *orderA = (struct emp *)a;
struct emp *orderB = (struct emp *)b;
return ( orderA->d.year - orderB->d.year );
}
int main ()
{
int i;
struct emp e[5];
for (i = 0;i < 5;i++)
{
scanf("%s %d %d %d", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
qsort(e, 5, sizeof(struct emp), compare);
for (i = 0;i < 5;i++)
{
printf("%s %d %d %d\n", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
return 0;
}
When you want scanf() to scan your stuff, you have to pass addresses of stuff, not the actual stuff. (If you do not pass the address of something to scanf(), then how can scanf() store a value in it?)
Now, in C when you refer to an array such as e[i].name you are actually referring to the address of the first element of the array, so you do not have to do anything special about that. (Besides to be careful to not enter more than 9 characters for name, wh00ps, that's extremely unsafe, be careful!)
But with integers, such as e[i].d.day etc, you can't just pass the int as it is, because scanf() expects pointers, so it will treat your int as a pointer to an int, so it will allow the user to enter a number, and then it will try to store the number at the location pointed by that pointer, which is just some random location in memory, and thus the segfault.
So, when you want to scan an int, you have to pass the address of the int, like this: &e[i].d.day
Except that when the integer is a field of a record, you cannot take its address, because it does not have an address of its own, it lives within some bits stored at an address.
So, I am afraid you are going to have to write a special function for reading those struct dates of yours, which will have to declare individual ints, pass their addresses to scanf(), and then store the resulting values in a struct date.
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'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;
}
}
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 was interested in accessing portions of memory I had allocated to get a better understanding of things, lets say I allocate 10 bytes with malloc and printf("%p", &foo) returns 0xff0a, would I be able to allocate 0xff0a->0xff1a (my hexadecimal math is bad at the moment) and access any one of those individual bytes?
I think I recall being used the keyword volatile along with a memory address for this, I am not sure what that code was able to do though..
I guess what I mean is how do I access a random byte in memory, cast as a char or integer that I can store in a pointer for accessing later on.
I'll assume you want to access a single byte from a multi-byte type such as an int or a short. The common idiom is to cast the address to a char* and deference that like so:
#include <stdio.h>
int main(void)
{
int foo = 0xDEADBEEF;
int i;
for (i = 0; i < 4; i++) {
printf("byte %d of foo is x%02X\n", i, *((unsigned char*)&foo + i));
}
return 0;
}
Output
$ ./a.out
byte 0 of foo is xEF
byte 1 of foo is xBE
byte 2 of foo is xAD
byte 3 of foo is xDE
Note The reason it looks backwards is due to x86 being little endian
printf("%p", &foo) prints the address of the pointer variable foo, not the address contained in foo (which is the one that came from malloc). You actually want:
printf("%p", (void *)foo);
If you wish to access the 10 bytes in memory pointed to by foo, you can simply use:
char *p = foo;
and then access p[0] through p[9].
If you allocate 10 bytes from 0xff0a, the address range is: 0xff0a to 0xFF14.
volatile forces the compiler to grab the stored value at that location every time. This has uses in hardware programming and multi-threaded applications.
This example stores the address of the int x into the pointer p:
int x = 5;
int * p = &x; //assign address of (operator &) x into a pointer
printf("%d\n", *p); // will display 5
You may want to use a union in order to always apply the same bunch of code to loop over the bytes area of your variable. The member 'byte' will always point to the same address as the others. You can include it into a struct in order to keep the size along with the union. A the end, you just call a function to print out or check the content of a bunch of memory...
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
union byteMap {
char* addressString;
void* addressInt;
unsigned char* byte;
};
struct structByteMap {
size_t size;
union byteMap map;
};
int main (int argc, char* argv[]) {
struct structByteMap map;
if (argc > 1) {
int temp = strtoimax(argv[1], NULL, 10);
map.map.addressInt = &temp;
map.size = sizeof(int);
} else {
map.map.addressString = "HELLO, YES HELLO";
map.size = strlen(map.map.addressString);
}
for (int i = 0; i < map.size; i++) {
printf("byte %d of param is x%02X\n", i, *(map.map.byte + i));
}
}