I'm very new to C, which I just started learning. Apologies if this question seems kind of dumb.
Can someone please explain why this doesn't work? Is there any way to accomplish something like this? Thanks so much!
struct test{
int arr[10];
};
void foo(struct test t){
t.arr[0] = 1;
}
int main() {
struct test t = {malloc(10*sizeof(int))};
foo(t);
printf("%d", t.arr[0]);
}
I'm not sure exactly why the t.arr[0] isn't assigned to 1.
C is an entirely pass-by-value language. foo receives a byte-wise copy of its argument, even for structures. Modifying the local variable t within foo does not modify the variable t in main.
The structure member int arr[10]; is automatically allocated as an array of ten int whenever memory for a struct test is allocated. You do not need to allocate it separately.
struct test t = {malloc(10*sizeof(int))};
is plainly wrong, causing the following diagnostics to be reported by gcc:
foo.c: In function ‘main’:
foo.c:13:22: warning: initialization of ‘int’ from ‘void *’ makes integer from pointer without a cast [-Wint-conversion]
13 | struct test t = {malloc(10*sizeof(int))};
| ^~~~~~
foo.c:13:22: note: (near initialization for ‘t.arr[0]’)
foo.c:13:21: warning: missing braces around initializer [-Wmissing-braces]
13 | struct test t = {malloc(10*sizeof(int))};
| ^
|
If you do not see diagnostics like these, you should turn up your compiler warnings.
gcc or clang use -Wall and -Wextra,msvc use /W4 or /Wall.If you do see diagnostics like these, do not ignore them with
gcc or clang use -Werror,msvc use /WXto make sure you can't.
Passing a pointer value allows you to dereference that pointer, and make modifications to the object that it points to:
#include <stdio.h>
#include <stdlib.h>
struct test{
int arr[10];
};
void foo(struct test *t){
t->arr[0] = 1;
}
int main() {
struct test t = { 0 };
foo(&t);
printf("%d\n", t.arr[0]);
}
1
As a caveat, if a structure contains a pointer, that pointer is of course copied by value to the local structure. This means whatever it points to is shared by both structures (for as long as their lifetimes overlap).
It is possible to do the following
#include <stdio.h>
#include <stdlib.h>
struct test{
int *arr;
};
void foo(struct test t){
t.arr[0] = 1;
}
int main() {
int array[10];
struct test t = { .arr = array };
foo(t);
printf("%d", t.arr[0]);
}
but this is generally not a great design pattern.
You need to pass the pointer to the structure to function foo() to allow foo() to update the structure t. I have updated your code at various points with comments. Please also note that malloc() is not required for structure t because of the way it is declared... the OS will set aside stack space for the structure. If you had declared only a pointer of type struct t, then yes, you would need malloc().
Runnable code available here.
#include <stdlib.h>
#include <stdio.h>
struct test{
int arr[10];
};
void foo(struct test *t){ /* updated: pointer of type struct t */
t->arr[0] = 1; /* updated. Access pointer struct members like this ( -> ) -- not the dot syntax */
}
int main() {
struct test t; /*updated -- this declaration already allocates space for the array in t -- see output from printf() */
foo(&t); /* updated -- foo() needs a pointer to the struct. So we pass the address of t (&t) */
printf("t.arr[0] = %d\nsizeof(t) = %d\n", t.arr[0], sizeof(t));
}
Output:
t.arr[0] = 1 /* It works! */
sizeof(t) = 40 /* See? 40 bytes allocated already (on my platform). */
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With