Function arguments within a function - c

I have the following code:
include <stdlib.h>
typedef struct foo{
int x;
}Foo;
void funcY(Foo *f1)
{
printf("%d", f1.x);
}
void funcX(Foo *f1)
{
printf("%d", f1.x);
funcY(f1); <---- is this correct?
}
int main()
{
Foo *foo1 = (struct foo *)malloc(sizeof(struct foo));
foo1.x = 10;
funcX(foo1);
return 0;
}
I don't know exactly how to label this problem. What is the best way for me to approach this?

funcY(f1); <---- is this correct?
Yes, this particular line is correct. However, several other parts that aren't: specifically, accessing struct members by pointer needs -> operator, rather than a dot:
printf("%d", f1->x);
Another small issue is that one should not cast malloc in C:
Foo *foo1 = malloc(sizeof(struct foo));
Finally, you are missing a call to free(foo) to deallocate malloc-ed memory. Note that you do not have to use malloc - allocate the struct in the automatic store, and use & to access its address:
int main()
{
Foo foo1;
foo1.x = 10;
funcX(&foo1);
return 0;
}

funcY(f1) is correct - it passes the Foo pointer to funcY, and since funcY accepts a Foo pointer we can assume it'll work as intended.
printf("%d", f1.x);, however, is not correct. f1 is a Foo pointer, not a Foo. To access it's x field you need to derefer it first - (*f1).x - or use the sytactic sugar f1->x.

Related

Struct pointer and its pointer attribute issue

Has this code undefined behaviour which means for s is mandatory to allocate memory or is ok this way ?
PS: what is the difference between
struct X* x = (struct X*)malloc(sizeof(struct X));
and
struct X* x = (struct X*)malloc(sizeof(x));
and
struct X* x = (struct X*)malloc(sizeof *x);
Thank you.
#include <stdio.h>
#include <stdlib.h>
struct X
{
int x;
char* s;
};
int main()
{
struct X* x = (struct X*)malloc(sizeof(struct X));
x->x = 10;
// x->s = (char*)malloc(10);
// memcpy...
x->s = "something";
printf("is ok?");
return 0;
}
Rather than throw my own interpretation at you i felt it would be more helpful to share a link that might clarify what you are aiming to achieve:
https://www.geeksforgeeks.org/new-vs-malloc-and-free-vs-delete-in-c/
When you create a pointer i see that you have added the pointer to your char* variable / struct, but when calling them the use of the ampersand & is used as a reference to the address in the memory.
But not applied quite right using the int variable when declaring it no '*' and then referencing the location using '&'.
This is fine. Since s is part of the struct, allocating memory for the struct allocates memory for s. I would strongly suggest changing the type of s to be a const pointer, since it points to a literal which, because it's a type of constant, cannot be modified.
You cannot do s[0]='n'; after this. You did not allocate any space to hold any string other than the unmodifiable literal "something".

Is there a way to make a variable survive 1 scope out of the current one?

I want to make a function that returns a pointer to a locally-defined variable. For the sake of argument, I'll call the function struct awesome *makeCoolStruct() (I don't want to declare the variable in the outer scope which should have the call struct awesome coolness = makeCoolStruct(); because the function will be called in more than one place).
I understand why the compiler errors out when I try doing that - the local variable will be 'destroyed' as soon as the program exits that scope, so the pointer will basically be invalid.
I looked up how to return a pointer to a local variable in a function, and while I get why malloc would work, that defeats the purpose of trying to do it this way, because malloc, as far as I understand, keeps the variable for as long as the program runs - or until free is called. However, that means that I'll have to have free called at the end of anything that calls my function. At that point, I'd be better off declaring the variable in every calling scope and then passing a pointer to it like makeCoolStruct(&existingVariable);.
If, however, there's a way to declare "keep this variable for 1 position higher in the stack" (which would obviously produce a compilation error in the global scope since there are no higher positions in the stack), then I could return a pointer and it'll exist just fine for as long as I need it to, wherever I decide to call struct awesome x = makeCoolStruct(); (I'm aware of the mutability issues - I'm not looking for mutability). I could truly return anything I want in a function from that point on, not just stuff that was passed in.
I haven't really tried anything because I don't know of anything that would work.
I expect to be able to return a pointer to a local variable after doing whatever keeps the variable for one scope higher, without having to do any preparations for the function call when I call it (creating a variable for it to use for the output instead of just assigning the output to something.
What you're asking isn't possible in C, but here are some alternatives:
Passing a stack variable in:
typedef struct {
int a;
int b;
} Foo;
void bar(Foo* foo)
{
foo->a = 5;
}
int main(void)
{
Foo foo = {0};
bar(&foo);
return 0;
}
Returning the struct directly:
Foo bar(void)
{
Foo foo = {1, 2};
return foo;
}
int main(void)
{
Foo foo = bar();
return 0;
}
Managing the memory manually:
Foo* bar(void)
{
Foo* foo = malloc(sizeof(*foo));
return foo;
}
int main(void)
{
Foo* foo = bar();
free(foo);
return 0;
}
Lastly, if you really hate whoever is going to inherit this project, you could always use a macro:
#define FOO(X) \
Foo X = {0}; \
bar(&X);
Although not recommended, it is actually safe to return a pointer to a static variable, assuming your program is not multithreaded.
struct myStruct {
int x;
char y;
};
struct myStruct *foo()
{
static struct myStruct bar = {.x = 0, .y = 'a'};
return &bar;
}
I would never write something like that, but it is safe in the sense that it does not invoke undefined behavior.
And just in case you did not know, it's perfectly cool to return a struct. You don't need malloc for that. This would be fine:
struct myStruct foo()
{
struct myStruct bar = {.x = 0, .y = 'a'};
return bar;
}

Type punning and malloc'ed memory

I originally asked this question: Type Punning with Unions and Heap
And not wanting the question to keep evolving to the point that anyone reading in the future had no idea what the original question was, I have a spin off question.
After reading this site:
https://kristerw.blogspot.com/2016/05/type-based-aliasing-in-c.html
Near the bottom it talks about malloc'd memory. Is it safe to say that casting from one pointer type to another pointer type is safe when memory is on the heap?
Example:
#include <stdio.h>
#include <stdlib.h>
struct test1
{
int a;
char b;
};
struct test2
{
int c;
char d;
};
void printer(const struct test2* value);
int main()
{
struct test1* aQuickTest = malloc(sizeof(struct test1));
aQuickTest->a = 42;
aQuickTest->b = 'a';
printer((struct test2*)aQuickTest); //safe because memory was malloc'd???
return 0;
}
void printer(const struct test2* value)
{
printf("Int: %i Char: %c",value->c, value->d);
}
And guessing it might not be safe. What would be the proper way to do this with memcpy? I will attempt to write an example with a function of what might hopefully work?
struct test2* converter(struct test1* original);
int main()
{
struct test1* aQuickTest = malloc(sizeof(struct test1));
aQuickTest->a = 42;
aQuickTest->b = 'a';
struct test2* newStruct = converter(aQuickTest);
printer(newStruct);
return 0;
}
struct test2* converter(struct test1* original)
{
struct test2* temp;
memcpy(&temp, &original, sizeof(struct test2));
return temp;
}
void *pnt = malloc(sizeof(struct test1));
What type has the memory behind pnt pointer? No type. It is uninitialized (it's value is "indeterminate"). There is just "memory".
Then you do:
struct test1* aQuickTest = malloc(sizeof(struct test1));
You only cast the pointer. Nothing happens here. No assembly is generated. Reading uninitialized memory is undefined behavior tho, so you can't read from aQuickTest->a (yet). But you can assign:
aQuickTest->a = 1;
This writes to an object struct test1 in the memory. This is assignment. You can now read aQuickTest->a, ie. print it.
But the following
printf("%d", ((struct test2*)aQuickTest)->a);
is undefined behavior (although it will/should work). You access the underlying object (ie. struct test1) using a not matching pointer type struct test2*. This is called "strict alias violation". Dereferencing an object (ie. doing -> or *) using a handle of not compatible type results in undefined behavior. It does not matter that struct test1 and struct test2 "look the same". They are different type. The rule is in C11 standard 6.5p7.
In the first code snipped undefined behavior happens on inside printf("Int: %i Char: %c",value->c. The access value-> accesses the underlying memory using incompatible handle.
In the second code snipped the variable temp is only a pointer. Also original is a pointer. Doing memcpy(&temp, &original, sizeof(struct test2)); is invalid, because &temp writes into the temp pointer and &original writes into the original pointer. No to the memory behind pointers. As you write out of bounds into&temppointer and read of bounds from&originalpointer (because most probablysizeof(temp) < sizeof(struct test2)andsizeof(original) < sizeof(struct test2)`), undefined behavior happens.
Anyway even if it were:
struct test1* original = &(some valid struct test1 object).
struct test2 temp;
memcpy(&temp, original, sizeof(struct test2));
printf("%d", temp.a); // undefined behavior
accessing the memory behind temp variable is still invalid. As the original didn't had struct test2 object, it is still invalid. memcpy doesn't change the type of the object in memory.

Segfault while accessing dynamicly allocated C struct array

I have the following struct that is defined in the following way
typedef struct _abcd {
int a;
unsigned long b;
void (*c)(int);
int d;
} abcd_t, *abcd;
Now i have the following code
static abcd foo
int set_size(int size){
foo = malloc(sizeof(abcd) * size);
}
This code for some reason gives me segfault when accessing some of the properties of array members.
But i have noticed that if i change the malloc line to the following - it fixes the issue
foo = malloc(sizeof(foo[0]) * size);
I find it strange as obviously sizeof(foo[0]) = sizeof(abcd)
So what is exactly the difference here?
Thanks
obviously sizeof(foo[0]) = sizeof(abcd)
It is not the same since you typedefed abcd to be a *pointer* to struct _abcd.
Use
foo = malloc(sizeof(*foo) * size);
to have robust code even if the type of foo should change at some point.
Your
foo = malloc(sizeof(foo[0]) * size);
is essentially the same since foo[0] is just syntactic sugar for *(foo + 0) which becomes *foo.
The bug is you're allocating sizeof(abcd) and that's a pointer, not a struct. You want sizeof(abcd_t) or sizeof(*abcd).

C: Accessing pointer to pointer to struct element from pointer to structure

I want to access members of a struct from double pointer but I get the error
"error: expected identifier before ‘(’ token"
C Double Pointer to Structure
double pointer to struct inside struct
:
struct test{
struct foo **val;
};
struct foo{
int a;
}
int main (){
struct test *ptr = (struct test *)malloc(sizeof(struct test));
ptr->val = &foo;
/*foo is already malloced and populated*/
printf ("Value of a is %d", ptr->(*val)->a);
}
I've also tried:
*ptr.(**foo).a
You want to do this:
#include <stdio.h>
#include <stdlib.h>
struct test {
struct foo **val;
};
struct foo {
int a;
};
int main(void) {
struct test* test_ptr = malloc(sizeof(struct test));
struct foo* foo_ptr = malloc(sizeof(struct foo));
foo_ptr->a = 5; // equivalent to (*foo_ptr).a = 5;
test_ptr->val = &foo_ptr;
printf ("Value of a is %d\n", (*(test_ptr->val))->a);
free(test_ptr);
free(foo_ptr);
return 0;
}
Output:
C02QT2UBFVH6-lm:~ gsamaras$ gcc -Wall main.c
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
Value of a is 5
In my example:
I allocate dynamically space for a struct test.
I allocate dynamically space for a struct foo.
I assign the value 5 to the member a of foo_ptr.
I assign the address of the allocated object of struct foo to the
member val of test_ptr.
I print member a the struct that the double pointer val points
to.
Note, in your example: struct foo is a type, so it doesn't make sense to ask for its address.
Also, you were missing a semicolon when you were done with the declaration of struct foo.
Oh, and make sure not to cast the return value of malloc().
in ptr->val = &foo;, foo is a struct (you declared it in lines 5 to 7). Taking its address does not give a **, but only a *.
Also it seems multiple things have the same names; is a foo the name of a structure or an instance of it, or both?
Then, when you dereference it: ptr->(*val)->a does seem the wrong sequence.
as ptr->val is the address of foo (that's what you assigned in the line above it), what would ptr->(*val) be??
I think ptr->val.a would give you your a. But still, the val is declared as a ** and consistently used as a *. It might work, but makes not much sense.

Resources