I have a problem, because while loading data from the console, a bug is popping up I think it's a tricky thing to pass the indicator through the function, but I don't know how to fix it.
#include<stdio.h>
#include<stdlib.h>
typedef struct rn{
int n; /**numerator**/
unsigned d; /**denomirator**/
} rationalNumber;
typedef struct dot{
rationalNumber x;
rationalNumber y;
} point;
int gcd(int a, int b)
{
if(b!=0)
return gcd(b,a%b);
return a;
}
void input(rationalNumber *a)
{
int nwd;
if (scanf("%d/%u",&(a->n), &(a->d)) == 1) a->d=1;
else
{
nwd = abs(gcd(a->n, a->d));
a->n = a->n/nwd;
a->d = a->d/nwd;
}
}
void load_point(point *a, void(*function)(rationalNumber *))
{
function(&a->x);
function(&a->y);
}
int main(void)
{
rationalNumber *z;
point *a;
load_point(a, input);
return 0;
}
I've got this message : Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
in this place : if (scanf("%d/%u",&(a->n), &(a->d)) == 1) a->d=1;
You're creating pointers that point to nothing in particular and then pass these on to the function which never initializes them, allocates memory for them, and trusts that they're valid, but they're not.
Remember that point* a is a pointer, not an allocation.
An easy solution is to use local variables instead of pointers:
int main(void)
{
rationalNumber z;
point a;
load_point(&a, input);
return 0;
}
Related
This question already has answers here:
How to change value of variable passed as argument?
(4 answers)
Closed 5 years ago.
When designing a game entity system in C, I attempted an "equals-free" initialization approach. I was surprised to see a linter tell me there was a memory leak at the end of my init function, and that my variable ent was never initialized in the following code. It turned out to be right because I got a "bus error":
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent = malloc(sizeof(*ent));
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
What I thought the above code would do, was take my empty ent pointer supplied as an argument, tell it to point to some newly allocated memory, and then fill in that memory and everything would be fine. I have no idea what it's really doing to cause a "bus error", am I missing something critical about pointers and malloc?
I vaguely remember seeing something very similar to this done before in some C code (equals-free struct initialization) and I would strongly prefer to use an equals-free initialization style similar to this (broken) code if such a thing is possible in C.
Move the malloc call outside the initialization function:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent = malloc(sizeof(*ent))))
return 1;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
You're assigning the pointer to the allocated block to a local variable (ent). That can't affect the ent in main.
If you wanted to keep the malloc in entity_init, you should use a double pointer, but you should also change the signature to allow for a way to signal malloc failure from entity_init
int entity_init(entity_t **ent, int _x, int _y)
{
if(NULL==(*ent = malloc(sizeof(**ent))))
return -1;
(*ent)->x = _x;
(*ent)->y = _y;
}
int main(void)
{
entity_t* ent;
if(0>entity_init(&ent, 10, 24))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
A more usual pattern for this would be:
entity_t *entity_new(int _x, int _y)
{
entity_t *ent = malloc(sizeof(*ent));
if (NULL==ent)
return NULL;
ent->x = _x;
ent->y = _y;
return ent;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent=entity_new(10,24)))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
If you must allocate within the entity_init() function, you need to either return a pointer to the allocation, or add a layer of indirection by making ent a pointer to pointer to entity_t. In the posted code, within entity_init() ent is a copy of the pointer which was passed to the function. Any changes made to this pointer, such as assigning the address of a memory allocation to the pointer, will not be visible from the calling function since this copy will cease to exist after the function returns.
Also, note that you need to check the value returned from malloc() to be sure that the allocation was successful. If successful, the function can continue with the initialization process; if not, ent can remain a null pointer, which should be checked in the calling function:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t **ent, int _x, int _y)
{
*ent = malloc(sizeof **ent);
if (*ent) {
(*ent)->x = _x;
(*ent)->y = _y;
}
}
int main(void)
{
entity_t *ent;
entity_init(&ent, 10, 24);
if (ent == NULL) {
fprintf(stderr, "Allocation failure in entity_init()\n");
exit(EXIT_FAILURE);
}
printf("Entity: x%d y%d\n", ent->x, ent->y);
return 0;
}
Program output:
Entity: x10 y24
int f(){
struct NUMBER {
int A;
int B;
};
struct NUMBER *num = malloc(sizeof(struct NUMBER));
num->A = 1;
num->B = 2;
int x = num->B;
return x;
}
int main(){
int z = f();
printf("%d\n", z);
}
Obviously, ./a.out will show 2.
My question: Can I access struct member by an argument of function? i.e. f(A) return 1, and f(B) return 2. Thanks a lot.
Not at all elegant, but I think it shows you what you need to do/know.
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
struct NUMBER {
int A;
int B;
};
struct NUMBER extNumber = {1, 2};
int f(int offset) {
int iRet = -1;
if (offset == offsetof(struct NUMBER, A)) {
iRet = extNumber.A;
} else if (offset == offsetof(struct NUMBER, B)) {
iRet = extNumber.B;
}
return iRet;
}
int main (int argc, char **argv) {
struct NUMBER number;
int iVal;
iVal = f(offsetof(struct NUMBER, A));
printf ("A : %d\n", iVal);
iVal = f(offsetof(struct NUMBER, B));
printf ("B : %d\n", iVal);
}
Can I access struct member by an argument of function?
I think you are also assuming struct is not visible outside the function. Now if the person who wrote main does not have visibility into the function (say it is part of a library), then the answer is NO.
Otherwise if author of main can see internals of the function, then: Can someone come up with a fancy way to access struct member inside the function via function argument? Towards that lets think what does f(A) mean? Here, A is a name of struct member, so do you mean passing char A to f and translating that to struct member inside f [e.g. result = *(int *)num+(inchar-'A') where inchar is aninput parameter to the function of type char]. Similarly, one can imagine other ways.
As far as I understand your problem, the cleanest and most "C-like" solution is to pass a pointer to your struct to f(), where you populate it:
typedef struct _NUMBER
{
int A;
int B;
}
NUMBER;
void f (NUMBER* pvNumber)
{
pvNumber->A = 1;
pvNumber->B = 2;
return;
}
Call it like this:
int main ()
{
NUMBER vNumber;
int z;
f (&vNumber);
z = vNumber.A; // or vNumber.B
return 0;
}
So you don't select the desired member inside f(), but outside of it.
Yes. you need to define some way to access to member desired, this is usually done with constants, or an enum. As an aside, you should always check the pointer returned by malloc() before using it.
#define GET_A (0)
#define GET_B (1)
int f(int selector){
struct NUMBER {
int A;
int B;
};
int result;
struct NUMBER *num = malloc(sizeof(struct NUMBER));
if (!num)
return -1; // or some other error code...
num -> A = 1;
num -> B = 2;
switch(selector)
{
case GET_A: result = num->A; break;
case GET_B: result = num->B; break;
// etc... if you have more members in your struct.
default: result = -1; break; // some error code.
}
free(num)
return result;
}
int main(){
int z = f(GET_B);
printf( "%d\n" , f(GET_B));
}
#include<stdio.h>
void f(int *p) {
static int data = 5;
p=&data;
}
int main(void) {
int *ip=NULL;
f(ip);
printf("%d\n", *ip);
return 0;
}
if it is possible.
what is cause error?
how can I fix the code?
In this way you end up changing the value of a local pointer, you need to pass a pointer to pointer (&) from main and use the dereference operator (*) in the function:
#include <stdio.h>
void f(int **p) {
static int data = 5;
*p = &data;
}
int main(void) {
int *ip = NULL;
f(&ip);
printf("%d\n", *ip);
return 0;
}
But usually we prefer to work with the same level of indirection returning the address from the function, this is easier to read (at least for me):
#include <stdio.h>
int *f(void) {
static int data = 5;
return &data;
}
int main(void) {
int *ip = f();
printf("%d\n", *ip);
return 0;
}
You have to pass a pointer to the pointer to change the value of the actual pointer:
void some_fun(int **p)
{
static int i = 10;
*p = &i;
}
That being said, it is not necessarily advisable to do that. The only direct use I could think of is to delay the execution of the initialization of a global until its first use.
I have read a lot of questions of stackoverflow, but couldn't find any solutions on how to deal with this problem of allocating and manipulating pointers inside functions: Can anybody please tell me what's wrong with this code? (I want to allocate and assign values to *D through pointerpass and print the same through pointerprint)
#include<stdio.h>
#include<stdlib.h>
float *D;
void pointerpass(float **ptr1)
{
*ptr1=(float*)malloc(3*sizeof(float));
*(ptr1+0)=1.33;
*(ptr1+1)=2.33;
*(ptr1+2)=3.33;
}
void pointerprint(float **ptr2)
{
int j=0;
for (j=0;j<3;j++)
printf("\n%f\n",*(ptr2+j));
}
int main()
{
pointerpass(&D);
pointerprint(&D);
return 0;
}
Here we go
#include<stdio.h>
#include<stdlib.h>
float * pointerpass(){
float *ret = malloc(3*sizeof(float));
ret[0] = 1.33f;
ret[1] = 2.33f;
ret[2] = 3.33f;
return ret;
}
void pointerprint(float *array) {
int j=0;
for (j=0;j<3;j++) {
printf("\n%f\n",array[j]);
}
}
int main() {
float *x = pointerpass();
pointerprint(x);
free(x); // We do not like memory leaks
return 0;
}
void pointerpass(float **ptr1){
*ptr1=(float*)malloc(3*sizeof(float));
(*ptr1)[0]=1.33;
(*ptr1)[1]=2.33;
(*ptr1)[2]=3.33;
}
void pointerprint(float **ptr2){
int j=0;
for (j=0;j<3;j++)
printf("\n%f\n", (*ptr2)[j]);
}
I keep geeting a segfault in the main function. I create a pointer to a struct I created and I pass it's reference to another function which allocates and reallocates memory. Then accessing it in the main function (where it was originally defined) causes a segfault.
Here is my test code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char desc[20];
int nr;
} Kap;
void read(Kap *k);
int main(void) {
Kap *k = NULL;
read(k);
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
void read(Kap *k) {
int size = 3;
k = (Kap*) calloc(size, sizeof(Kap));
k[0].nr = 1;
k[1].nr = 2;
k[2].nr = 3;
strcpy(k[0].desc, "hello0");
strcpy(k[1].desc, "hello1");
strcpy(k[2].desc, "hello2");
size *= 2;
k = (Kap*) realloc(k, sizeof(Kap)*size);
if(k == NULL) {
printf("ERROR\n");
exit(EXIT_FAILURE);
}
k[3].nr = 4;
k[4].nr = 5;
k[5].nr = 6;
strcpy(k[3].desc, "hello3");
strcpy(k[4].desc, "hello4");
strcpy(k[5].desc, "hello5");
}
What am I doing wrong?
Here's a simplified version of the problem you are having:
#include <stdio.h>
void func(int x)
{
x = 10;
}
int main()
{
int x = 5;
printf("x = %d\n", x);
func(x);
printf("x = %d\n", x);
}
The same reason x does not change is the reason that k does not change in your program. A simple way to fix it is this:
Kap *read()
{
Kap *k = calloc(...);
...
k = realloc(k, ...);
...
return k;
}
int main()
{
Kap *k = read();
...
}
The problem is you're not passing the pointer back to main(). Try something like this instead:
Kap * read();
int main(void) {
Kap *k = read();
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
Kap * read() {
... everything else you're already doing ...
return k;
}
The code you showed passes a pointer by value into read(). The subroutine can use that pointer (though it's kind of useless since its local copy is immediately changed), however changes made within read() do not bubble back to its caller.
My suggestion is one method of allowing read() to send the new pointer back up, and it's probably the right method to choose. Another method is to change read()s signature to be void read(Kap **);, where it will receive a pointer to a pointer -- allowing it to modify the caller's pointer (due to being passed by reference).