I have a project in which I have to make a basic database in C. My problem lies that keep passing a variable n from function to function and at one point the value changes.
I have made a test program which illustrates the same issue I'm having:
#include <stdio.h>
#include <stdlib.h>
void functionTWO(int *n)
{
printf("\n%d",*n);
}
functionONE(int *n)
{
int i=0;
i++;
i++;
*n = i;
printf("\n%d", *n);
functionTWO(&n);
}
int main()
{
int n=0;
printf("%d",n);
functionONE(&n);
return 0;
}
The n in the second function is displayed as a very very high number, e.g.:
0
2
2752268
Now, I know this probably is intended, but could you guys kindly explain why this happens this way?
In your functionONE(), n is already a pointer. You don't need to pass the address of the pointer if you intend to change that value-at-the-address.
As an advice, always check the data types and enable the compiler warnings to help you.
functionONE()
your are passing a address of address. So it's printing address of n.
Now you want a correct output then n as double pointer **n.
void functionTWO(int **n)
{
printf("\n%d",**n);
}
First of all, in C int & n is not the reference of n, it is it's address.Now, what you've done is created an int - sent it's address to functionONE - did something to the value in that address and then sent the the argument's address to functionTWO, instead of sending the argument itself, becuase it's already a pointer. Do this instead:
#include <stdio.h>
#include <stdlib.h>
void functionTWO(int *n)
{
printf("\n%d",*n);
}
functionONE(int *n)
{
int i=0;
i++;
i++;
*n = i;
printf("\n%d", *n);
functionTWO(n); // <-- send the pointer, not it's address
}
int main()
{
int n=0;
printf("%d",n);
functionONE(&n);
return 0;
}
In functionONE, n is int *, just a pointer, when you do functionTWO(&n);, you get the address of n, so it output a big value.
The value being printed in functionTWO function is the address of the pointer variable n declared in functionONE.In that case you can either modify functionTWO like this
void functionTWO(int **n)
{
printf("\n%d",**n);
}
or
Just pass the value of the pointer variable like this
functionTWO(n);
Related
I want to create an array of structs based on one struct definition, and initialize each one with a different int value.
Then, I want to print this value, using a function pointer that points to a print function.
Define a struct (includes an int and a function pointer).
create an array of 10 structs of the same definition.
set different values for each one of them.
send this value for a function that is pointed to by a function
pointer that is also located in the struct
This is my code:
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_SIZE 10
void Print(int num);
typedef struct print_me
{
int x;
void (*Print)(int x);
};
struct print_me my_prints[ARRAY_SIZE];
int main()
{
size_t i = 0;
for (i = 0; i < ARRAY_SIZE; ++i)
{
my_prints[i].x = i;
my_prints[i].Print(my_prints[i].x);
}
return 0;
}
void Print(int num)
{
printf("%d\n",num);
}
I'm still learning the ideas of function pointer and structs , so I'll be glad to get some tips and suggestions that will help me to understand my mistakes here.
Thanks.
For starters there is no any sense to use the typedef specifier in this declaration
typedef struct print_me
{
int x;
void (*Print)(int x);
};
without specifying a typedef name. You could write for example
typedef struct print_me
{
int x;
void (*Print)(int x);
} print_me;
In the for loop you need to initialize the data member Print with the address of the function Print. For example
for (i = 0; i < ARRAY_SIZE; ++i)
{
my_prints[i].x = i;
my_prints[i].Print = Print;
}
then in a second for loop you could call the function like
for (i = 0; i < ARRAY_SIZE; ++i)
{
my_prints[i].Print( my_prints[i].x );
}
As with usual pointers, you have to set a pointer value before you can use it. So that it points somewhere.
Add:
my_prints[i].Print = &Print;
// or, it means the same, & is optional
// my_prints[i].Print = Print;
my_prints[i].Print(my_prints[i].x); // now ok
before calling my_prints[i].Print() so that the pointer will point to function Print before calling it.
Side note with a fun fact: because of the strange C rules, dereferencing the function pointer is not needed, and you can even like "dereference" the function pointer multiple times, like (****my_prints[i].Print)(). See ex this question.
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 6 years ago.
Ok, so the idea of the task I have (I am the student) is to allow user to insert a string of words in this form: num1_num2_num3..._numN. The code should create an array X, give it memory dynamically and then I should fill X with numbers from string user inserted. Simple as that. Well, in the function stringuniz() I thought I had it all figured out but it simply wont work. It gets the first number well but it then stops and I think its because of the break. Break behaves (if I am right) like it breaks the entire code and not just the loop. Do you guys have an idea why is this happening?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void stringuniz(char *);
int *x;
int main(){
char s[50];
int i;
puts("Unesite string brojeva u formatu br1_br2_...brN: ");
gets(s);
stringuniz(s);
for(i=0;i<(sizeof(x)/sizeof(int));i++)
printf("%d",x[i]);
}
void stringuniz(char *s){
int duz,c=0,i,j,k=0,m=0;
char b[10];
duz=strlen(s);
for(i=0;i<duz;i++)
if(s[i]=='_')
c++;
x=(int*)malloc((c+1)*sizeof(int));
if(x==NULL) exit(1);
for(i=0;i<c+1;i++){
for(j=m;j<duz;j++){
if(s[j]!='_'){
b[k++]=s[j];
m++;
}
else{
b[k]='\0';
x[i]=atoi(b);
k=0;
m++;
break;
}
}
}
}
This
(sizeof(x)/sizeof(int)
won't give you the size of the array. sizeof(x) is the bytesize of int* (likely 4 or 8).
You'll need to remember the size as implied by the number of _ in the string.
Also you have some off-by-one errors in there and for future reference, you might want to choose more descriptive variable names for code you decide to post publicly.
The code worked for me once I changed it to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void stringuniz(char *);
int *x;
int x_size = 0;
int main(){
char s[50];
int i;
puts("Unesite string brojeva u formatu br1_br2_...brN: ");
fgets(s,50,stdin);
stringuniz(s);
for(i=0;i<x_size;i++)
printf("%d\n",x[i]);
}
void stringuniz(char *s){
int duz,c=0,i,j,k=0,m=0;
char b[10];
duz=strlen(s);
for(i=0;i<duz;i++)
if(s[i]=='_')
c++;
x=malloc((c+1)*sizeof(int));
x_size = c+1;
if(x==NULL) exit(1);
for(i=0;i<=c+1;i++){
for(j=m;j<=duz;j++){
if(s[j]!='_' && s[j]!='\0'){
b[k++]=s[j];
m++;
}
else {
b[k]='\0';
x[i]=atoi(b);
k=0;
m++;
break;
}
}
}
}
void stringuniz(char *);
int *x;
int main(){
[...]
}
void stringuniz(char *s){
[...]
}
I don't know why many ppl teach it this way, but there is absolute no use in having main somewhere in the middle of a source file, and putting it at the end also allows you to get rid of the forward declarations. So, I would write it this way:
int *x;
void stringuniz(char *s){
[...]
}
int main(){
[...]
}
Then you should start using the space character more.
stringuniz(s);
for(i=0;i<(sizeof(x)/sizeof(int));i++)
printf("%d",x[i]);
In a comment, alain already pointed out, that sizeof(x) will return the size of a pointer. So, you need a different way to figure out the size of the array. One way is to add a variable size_t x_len; besides int * x;. Also, you should use curley brackets even for one line statements, believe me, not only makes it the code more readable, it also prevents introducing bugs on later changes.
for (i = 0; i < x_len; i++) {
printf("%d", x[i]);
}
.
void stringuniz(char *s){
int duz,c=0,i,j,k=0,m=0;
char b[10];
b will hold the word the user enters. If his word is longer then 9 characters, you get a buffer overflow here.
duz=strlen(s);
for(i=0;i<duz;i++)
if(s[i]=='_')
c++;
You are counting the number of words here. So, please use more descriptive names like num_words instead of c. BTW: This is the x_len mentioned above.
x=(int*)malloc((c+1)*sizeof(int));
No need to cast return value of malloc. Actually it might hide bugs. Also, I would use sizeof(*x) instead of sizeof(int), because if you change the type of x, in your statement, you also would have to change the malloc call. In my statement, the malloc call doesn't need to be touched in any way.
x = malloc((c+1) * sizeof(*x));
if(x==NULL) exit(1);
for(i=0;i<c+1;i++){
for(j=m;j<duz;j++){
if(s[j]!='_'){
b[k++]=s[j];
You are constantly overwriting b with the next word being read. Since you're not using it anyway, you can just skip this line.
m++;
}
else{
b[k]='\0';
x[i]=atoi(b);
k=0;
m++;
break;
And this break; only breaks out of the innermost for (j-loop.
}
}
}
}
Basically, why does it not just print the integers that are entered. Right now it just prints garbage value, but I do not know why it cannot access the values stored after it leaves the function. It only seems to get messed up after leaving the getIntegersFromUser function. If I run the for loop in the getIntegers function it does it properly, but why not in the main function?
Thanks in advance for your help.
#include <stdio.h>
#include <stdlib.h>
void getIntegersFromUser(int N, int *userAnswers)
{
int i;
userAnswers =(int *)malloc(N*sizeof(int));
if (userAnswers)
{ printf("Please enter %d integers\n", N);
for (i=0;i<N; i++)
scanf("%d", (userAnswers+i));
}
}
int main()
{
int i, M=5;
int *p;
getIntegersFromUser(M, p);
for (i=0;i<5;i++)
printf ("%d\n", p[i]);
return 0;
}
Also, this is a homework question, but it's a "Bonus Question", so I'm not trying to "cheat" I just want to make sure I understand all the course material, but if you could still try to give a fairly thorough explanation so that I can actually learn the stuff that would be awesome.
Pointers are passed by value. The function is using a copy of your pointer, which is discarded when the function ends. The caller never sees this copy.
To fix it, you could return the pointer.
int *getIntegersFromUser(int N)
{
int *userAnswers = malloc(...);
...
return userAnswers;
}
/* caller: */
int *p = getIntegersFromUser(M);
Or you could pass your pointer by reference so the function is acting on the same pointer, not a copy.
void getIntegersFromUser(int N, int **userAnswers)
{
*userAnswers = (int *) malloc(N*sizeof(int));
...
}
/* caller: */
int *p;
getIntegersFromUser(N, &p);
I expected the output of the following program to to be 5, but the compiler is displaying 20. Can someone please explain why?
#include <stdio.h>
int a=5;
change1(int *p);
int main(void)
{
int x=20,*ptr=&x;
change1(ptr);
printf("%d ",*ptr);
return 0;
}
change1(int *p)
{
p=&a;
}
You're passing a pointer, which causes the function to make a copy. In order to change it you have to pass a pointer to a pointer.
If you want to modify a pointer, you need to pass a pointer to pointer:
change1(&ptr);
and then:
void change1(int **p)
{
*p = &a;
}
Which of these codes is appropriate and why ?
code1:
void fun(int *p)
{
*p=200;
}
main(){
int *i_ptr;
fun(i_ptr);
printf("%d", *i_ptr);
}
Code2:
void fun(int *p)
{
*p=200;
}
main(){
int i;
fun(&i);
printf("%d", i);
}
is it okay to pass pointer's address ?
You asked:
Which of these codes is appropriate and why ?
The first one will lead to undefined behavior since i_ptr has not been initialized to point to a valid memory.
You can change it to:
int main(){
int i;
int *i_ptr = &i;
fun(i_ptr);
printf("%d", *i_ptr);
}
and it will be OK.
BTW, I also added int as the return type of main.
You also asked:
is it okay to pass pointer's address ?
It is clear to me how the question is related to the code you posted.