Am I allowed to use a variable being initialized inside a designated initializer?
Consider the following listing:
struct A {
int a;
int * const a_ptr;
};
struct A foo(int a) {
struct A result = {
.a = a,
.a_ptr = &result.a
};
return result;
}
demo
Am I allowed to use result in this designated initializer expression? Is this behavior defined? Is this code portable?
Update
My bad, the example contains a potential stack corruption. The listing should be:
struct A {
int a;
int * const a_ptr;
};
void foo(int a) {
struct A result = {
.a = a,
.a_ptr = &result.a
};
bar(&result);
}
The initialization by itself is fine.
At the time result is declared, its address (as well as the addresses of its fields) is constant. So it is safe to use &result.a in the initializer of result.
What is a problem however is that you're returning a copy of this structure. This copy contains the address of a local variable that no longer exists, so attempting to use the value of the a_ptr member of the returned struct will trigger undefined behavior.
The question has changed completely, here is my new answer:
Your code is fine, you can check this, it won't assert on any platform.
You pass the pointer to the local variable result to bar. In bar that local variable still exists p points to that variable (result). Therefore the a_ptr still points to result.a.
But I'm just wondering what you're trying to achieve here.
#include <assert.h>
struct A {
int a;
int* const a_ptr;
};
void bar(struct A *p)
{
assert(p->a_ptr == &p->a);
}
void foo(int a) {
struct A result = {
.a = a,
.a_ptr = &result.a
};
bar(&result);
}
int main()
{
foo(2);
}
BTW:
struct A result = {
.a = a,
.a_ptr = &result.a
};
is equivalent to this:
struct A result;
result.a = a;
result.a_ptr = &result.a;
but for latter you'd need to declare int* a_ptr; instead of int* const a_ptr;.
Related
I am trying to understand why the following code compiles and runs fine. I would expect any assignment using data inside f not to compile with a gcc error assignment of member āiā in read-only object. Is there some kind of exception, because data.i is allocated dynamically?
#include <stdio.h>
#include <stdlib.h>
struct a {
int *i;
};
void f(const struct a *data) {
data->i[0] = 55;
}
int main() {
struct a data;
data.i = malloc(2 * sizeof(int));
f(&data);
printf("%d\n", data.i[0]);
return 0;
}
const front of a struct will make it read-only. If the struct contains pointer members, then those pointers themselves will turn read-only. Not what they point at.
That is, const struct a will make the member i behave is if it was declared as int *const i;, meaning that the pointer itself cannot be changed to point elsewhere. The pointed-at data is still of read/write int though.
If you want to restrict access to i inside a function, you should make that function take a const int* parameter and pass the i member to that function.
In the below code, const indicates what data points to is not to be modified. data->i[0] = 55; does not modify the pointer data->i. Instead that line of code modifies the memory pointed to by data->i. This is allowed as pointer .i is int * and not const int *.
struct a {
int *i;
};
void f(const struct a *data) {
data->i[0] = 55;
}
You cant modify i but you can modify the objects referenced by i.
To prevent it you need to:
struct a {
const int *i;
};
I want to be able to access a struct variable from all functions in a .c file.
I assumed that the way is to declare the struct as static outside any function.
I have something like this:
static struct gameBoard current_game_board;
int foo() {
current_game_board = { .x = 1, .y = 2 }
}
This shouts "expected expression before '{' token". When I try the same with and int instead of a struct gameBoard it works.
Is it even possible with a struct? Is there a better way to save state across a file?
The Initializer list is for initializing objects. An Initialization is when you define a variable and explicitly assign it a value in the same go.
As you defined the variable outside the block already, you can't use an initializer list that way. Do this instead:
current_game_board.x = 1;
current_game_board.y = 2;
Also as #UnderDog pointed out, you are misunderstanding what static means. static for a variable at file scope denotes that it has internal linkage, i.e. it is restricted to the current translation unit and is not visible outside.
What you wanted is having the variable at file scope, which would work without the static qualifier too. You were right in choosing static though, as you should restrict access to everything that's not needed from outside. You just did it for the wrong reason.
If I understand you correctly, that you essentially want a global structure you can write to wherever, then define the structure and create a global pointer to it. Allocate the pointer anywhere, and you can use it wherever you like:
#include <stdio.h>
#include <stdlib.h>
typedef struct gameBoard {
int a;
int b;
} gameBoard;
gameBoard *current_gameboard; /* declare global pointer */
void prngameboard ()
{
printf ("\ncurrent_gameboard-> a: %d\ncurrent_gameboard-> b: %d\n\n",
current_gameboard-> a, current_gameboard-> b);
}
void setgameboard (int x, int y)
{
current_gameboard-> a = x;
current_gameboard-> b = y;
}
int main () {
/* allocate memory for pointer */
current_gameboard = malloc (sizeof *current_gameboard);
current_gameboard-> a = 1;
current_gameboard-> b = 2;
prngameboard ();
setgameboard (3, 4);
prngameboard ();
/* free memory allocated to pointer */
if (current_gameboard)
free (current_gameboard);
return 0;
}
output
$ ./bin/struct_global
current_gameboard-> a: 1
current_gameboard-> b: 2
current_gameboard-> a: 3
current_gameboard-> b: 4
Note: you should always check the return from malloc and test whether current_gameboard has been allocated before using it. Both have been omitted for brevity. let me know if you have questions.
You can possibly use:
static struct gameBoard current_game_board;
void foo(void) {
current_game_board = (struct gameBoard){ .x = 1, .y = 2 };
}
This assigns a 'compound literal' of the appropriate type to your global variable.
A once-only alternative is:
static struct gameBoard current_game_board = { .x = 1, .y = 2 };
These require C99 or better support, but the fact that you're trying suggests that you probably have that.
I'm writing a Gameboy ROM using the GBDK, which has an unstable version of malloc that I'm unable to get working. I'm also unable to return a struct within a struct. That leaves me trying to return a pointer, which is why I'm wondering if there is a way to avoid using malloc when returning a struct pointer?
What I'm basically trying to do is that I want to be able to write something like this:
create_struct(struct_name, char member_x, char member_y);
This is the code I have written using malloc:
struct point {
char member_x;
char member_y;
};
struct point *makepoint(char member_x, char member_y) {
struct point *temp = malloc(sizeof(struct point));
temp->member_x = member_x;
temp->member_y = member_y;
return temp;
};
There are various valid ways to return a pointer (to a struct, or any type of object), but the only way to return a pointer to a new object that didn't exist before the function was called is to use malloc, realloc, calloc, aligned_alloc (C11), or some implementation-defined allocation function (e.g. mmap on POSIX systems, etc.).
Other ways you could return a valid pointer include:
A pointer to an object with static storage duration. Only once instance of such an object exists, so this is usually a bad way.
A pointer that was passed to the function as an argument for use as a place to store the result. This can often be a good approach, since you pass off responsibility for obtaining the storage to the caller.
A pointer to an object obtained from some sort of global pool. This could be a very good approach in embedded systems and game design for low-end gaming devices.
Is it possible to return a pointer to a struct without using malloc?
I. Technically, yes. You can make your struct static so that it survives function calls:
struct foo *bar()
{
static struct foo f = { 1, 2, 3 };
return &f;
}
But I doubt you actually want to do this (since this has funny side effects, read up on the meaning of the static keyword). You have several different possibilities:
II. The approach what the C standard library takes is always making the caller implicitly responsible for providing the struct and managing memory. So instead of returning a pointer, the function accepts a pointer to struct and fills it:
void dostuff(struct foo *f)
{
foo->quirk = 42;
}
III. Or return the struct itself, it doesn't hurt, does it (it can even be move-optimized):
struct foo bar()
{
struct foo f = { 1, 2, 3 };
return f;
}
So, choose your poison.
just do something like:
void makepoint(struct point *dest, char member_x, char member_y) {
dest->member_x = member_x; // you had these wrong in your code, by the way
dest->member_y = member_y;
}
The structure will need to be "allocated" elsewhere (probably on the stack is your best bet).
You could pass the struct as a parameter and have the function initialize it :
struct point *makepoint(struct point *pt, char x, char y) {
pt->x = x;
pt->y = y;
return pt;
}
and then call it like this :
struct point pt;
makepoint(&pt, 'a', 'b');
but then you might as well just have done :
struct point pt = { 'a', 'b' };
Note that in this case (struct point only occupies 2 bytes) you can return struct point instead of struct point *, (this should not be done with large structs)
#include <stdio.h>
struct point {
char member_x;
char member_y;
};
struct point makepoint(char member_x, char member_y)
{
struct point temp;
temp.member_x = member_x;
temp.member_y = member_y;
return temp;
}
int main(void)
{
struct point t = makepoint('a', 'b');
printf("%c %c\n", t.member_x, t.member_y);
return 0;
}
If it is not possible to get malloc() fixed, then you may just want to manage your own pre-allocated points, and limit the number of points that can be "created". You would need to alter your points a little to allow for easier management:
union free_point {
union free_point *next;
struct point data;
};
union free_point free_point_pool[MAX_POINTS];
union free_point *free_point_list;
struct point *makepoint(char member_x, char member_y) {
static int i;
union free_point *temp;
temp = 0;
if (i == MAX_POINTS) {
if (free_point_list) {
temp = free_point_list;
free_point_list = temp->next;
}
} else {
temp = free_point_pool + i++;
}
if (temp) {
temp->data.x = x;
temp->data.y = y;
}
return &temp->data;
};
Then, instead of calling free() on the result returned by makepoint(), you should create a new function to place it on the free_point_list.
void unmakepoint (struct point *p) {
union free_point *fp = (union free_point *)p;
if (fp) {
fp->next = free_point_list;
free_point_list = fp;
}
}
The simplest thing is just to return a structure that has been created using named initializers, and do so in an inline function, so that there is zero overhead:
static inline struct point makepoint(char x, char y) {
return (struct point) { .x = x, .y = y };
}
Then you can call it like this:
struct point foo = makepoint(10, 20);
Couldn't be simpler!
Today I was teaching a couple of friends how to use C structs. One of them asked if you could return a struct from a function, to which I replied: "No! You'd return pointers to dynamically malloced structs instead."
Coming from someone who primarily does C++, I was expecting not be able to return structs by values. In C++ you can overload the operator = for your objects and makes complete sense to have a function to return your object by value. In C, however, you do not have that option and so it got me thinking what the compiler is actually doing. Consider the following:
struct MyObj{
double x, y;
};
struct MyObj foo(){
struct MyObj a;
a.x = 10;
a.y = 10;
return a;
}
int main () {
struct MyObj a;
a = foo(); // This DOES work
struct b = a; // This does not work
return 0;
}
I understand why struct b = a; should not work -- you cannot overload operator = for your data type. How is it that a = foo(); compiles fine? Does it mean something other than struct b = a;? Maybe the question to ask is: What exactly does the return statement in conjunction to = sign do?
You can return a structure from a function (or use the = operator) without any problems. It's a well-defined part of the language. The only problem with struct b = a is that you didn't provide a complete type. struct MyObj b = a will work just fine. You can pass structures to functions as well - a structure is exactly the same as any built-in type for purposes of parameter passing, return values, and assignment.
Here's a simple demonstration program that does all three - passes a structure as a parameter, returns a structure from a function, and uses structures in assignment statements:
#include <stdio.h>
struct a {
int i;
};
struct a f(struct a x)
{
struct a r = x;
return r;
}
int main(void)
{
struct a x = { 12 };
struct a y = f(x);
printf("%d\n", y.i);
return 0;
}
The next example is pretty much exactly the same, but uses the built-in int type for demonstration purposes. The two programs have the same behaviour with respect to pass-by-value for parameter passing, assignment, etc.:
#include <stdio.h>
int f(int x)
{
int r = x;
return r;
}
int main(void)
{
int x = 12;
int y = f(x);
printf("%d\n", y);
return 0;
}
When making a call such as a = foo();, the compiler might push the address of the result structure on the stack and passes it as a "hidden" pointer to the foo() function. Effectively, it could become something like:
void foo(MyObj *r) {
struct MyObj a;
// ...
*r = a;
}
foo(&a);
However, the exact implementation of this is dependent on the compiler and/or platform. As Carl Norum notes, if the structure is small enough, it might even be passed back completely in a register.
The struct b line doesn't work because it's a syntax error. If you expand it out to include the type it will work just fine
struct MyObj b = a; // Runs fine
What C is doing here is essentially a memcpy from the source struct to the destination. This is true for both assignment and return of struct values (and really every other value in C)
As far as I can remember, the first versions of C only allowed to return a value that
could fit into a processor register, which means that you could only return a pointer to
a struct. The same restriction applied to function arguments.
More recent versions allow to pass around larger data objects like structs.
I think this feature was already common during the eighties or early nineties.
Arrays, however, can still be passed and returned only as pointers.
There is no issue in passing back a struct. It will be passed by value
But, what if the struct contains any member which has a address of a local variable
struct emp {
int id;
char *name;
};
struct emp get() {
char *name = "John";
struct emp e1 = {100, name};
return (e1);
}
int main() {
struct emp e2 = get();
printf("%s\n", e2.name);
}
Now, here e1.name contains a memory address local to the function get().
Once get() returns, the local address for name would have been freed up.
SO, in the caller if we try to access that address, it may cause segmentation fault, as we are trying a freed address. That is bad..
Where as the e1.id will be perfectly valid as its value will be copied to e2.id
So, we should always try to avoid returning local memory addresses of a function.
Anything malloced can be returned as and when wanted
yes, it is possible we can pass structure and return structure as well. You were right but you actually did not pass the data type which should be like this struct MyObj b = a.
Actually I also came to know when I was trying to find out a better solution to return more than one values for function without using pointer or global variable.
Now below is the example for the same, which calculate the deviation of a student marks about average.
#include<stdio.h>
struct marks{
int maths;
int physics;
int chem;
};
struct marks deviation(struct marks student1 , struct marks student2 );
int main(){
struct marks student;
student.maths= 87;
student.chem = 67;
student.physics=96;
struct marks avg;
avg.maths= 55;
avg.chem = 45;
avg.physics=34;
//struct marks dev;
struct marks dev= deviation(student, avg );
printf("%d %d %d" ,dev.maths,dev.chem,dev.physics);
return 0;
}
struct marks deviation(struct marks student , struct marks student2 ){
struct marks dev;
dev.maths = student.maths-student2.maths;
dev.chem = student.chem-student2.chem;
dev.physics = student.physics-student2.physics;
return dev;
}
You can assign structs in C. a = b; is valid syntax.
You simply left off part of the type -- the struct tag -- in your line that doesn't work.
struct emp {
int id;
char *name;
};
struct emp get() {
char *name = "John";
struct emp e1 = {100, name};
return (e1);
}
int main() {
struct emp e2 = get();
printf("%s\n", e2.name);
}
works fine with newer versions of compilers.
Just like id, content of the name gets copied to the assigned structure variable.
struct var e2 address pushed as arg to callee stack and values gets assigned there. In fact, get() returns e2's address in eax reg. This works like call by reference.
#include <stdio.h>
struct emp {
int id;
char *name; /* This must point to valid memory, or replace with an array that holes the data, like this char name[128] */
};
struct emp bad() {
static char name[] = {'J', 'o', 'h', 'n', '\0'}; /* static enforces this array to be stored globally and not in the local stack which would not be valid after the function returns */
struct emp e1 = {404, name};
return (e1);
}
int main() {
struct emp e2 = bad();
printf("%s\n", e2.name);
}
I want to understand what this code means actually, esp. the last part where the function is put into curly braces. Is the broadcast_open function somehow calling the function broadcast_recv? If yes, how?
static void broadcast_recv(struct broadcast_conn *c, const rimeaddr_t *from)
{
printf("broadcast message received from %d.%d: '%s'\n",
from->u8[0], from->u8[1], (char *)packetbuf_dataptr());
}
static const struct broadcast_callbacks broadcast_call = {broadcast_recv};
static struct broadcast_conn broadcast;
PROCESS_THREAD(example_broadcast_process, ev, data)
{
broadcast_open(&broadcast, 129, &broadcast_call);
...
}
void broadcast_open(struct broadcast_conn *c, uint16_t channel, const struct broadcast_callbacks *u)
{
abc_open(&c->c, channel, &broadcast);
c->u = u;
channel_set_attributes(channel, attributes);
}
It seems that broadcast_callbacks is a struct defined something like this:
struct broadcast_callbacks
{
void (*callback)(struct broadcast_conn *, const rimeaddr_t *from);
};
Then the line
static const struct broadcast_callbacks broadcast_call = {broadcast_recv};
creates a new struct object whose member points to the broadcast_recv function. This member can now be used to call the broadcast_recv (which is probably part of what broadcast_open does).
You have probably seen simple variables initialized, e.g.:
int x = 4;
When it's an aggregate, such as a structure, braces are used around the initializer so the compiler knows where the initializer ends. In this case, it would appear that a function pointer is the first member of the struct.
int f(void) { return 1; }
struct t {
int (*f)(void);
int a, b, c;
char *d, *e, *f;
} a_t_instance = {
f
};
Someone can now call f() with (*a_t_instance.f)(), or even a_t_instance.f()
So yes, broadcast_open or something that it calls is probably calling broadcast_receive, using the pointer in the structure.