I have a struct defined as :
typedef struct pt {
int x;
int y;
}point;
I also have a stack push function declared as :
void push(point p);
Now whenever i wish to call this function, I can do the following :
point p = {x_value, y_value};
push(p);
I wanted to know if there is a less cumbersome workaround for this. Something which could enable me to do this in a single line. Maybe something like :
push((point){x_value, y_value});
Define a "constructor" function:
point make_point(int x, int y)
{
point result = {x, y};
return result;
}
Then
push(make_point(x, y));
The syntax you thought of works out of the box in C99:
typedef struct {
int x;
int y;
} point;
push((point){ 42, 1337 });
What's even better, the resulting literal is an lvalue, so you can take its address in case your push() function accepts a pointer:
void push(point *p);
// ...
push(&(point){ 42, 1337 });
Demo here.
Related
I wanted to create a function for my struct. I searched on the internet and found this two helpful links:
Can I define a function inside a C structure?
Define functions in structs
Most of the answers defined this:
typedef struct Point
{
int x;
int y;
void (*Print)(Point* p);
} Point;
Meaning that if you wanted to call the Print function on a struct you will have to pass the same point again. In other words you would do something like this:
somePoint.Print(&somePoint);
That works but it will be better if you don't have to pass &somePoint as an argument. In other words my goal is to achieve the same behavior by calling somePoint.Print(); instead of somePoint.Print(&somePoint); .
Anyways I am no expert in C and I was about to post this answer on those links:
#include <stdlib.h>
#include <string.h>
typedef struct Point
{
int x;
int y;
void (*Print)();
} Point;
void _print_point(Point* p)
{
printf("x=%d,y=%d\n", p->x, p->y);
}
void Point_Constructor(Point* p, int x, int y){
p->x = x;
p->y = y;
// create wrapper function
void inline_helper() { _print_point(p);}
p->Print = inline_helper;
}
int main(){
Point p1;
Point_Constructor(&p1,1,2);
p1.Print(); // I CAN CALL THE PRINT FUNCTION WITHOUT HAVING TO PASS AGAIN THE SAME POINT AS REFERENCE
return 0;
}
Why nobody suggested that? Is it safe if I run code like that?
I want to create a constructor using C.
What is the cleanest way to achieve this?
My attempt:
#include <stdio.h>
struct line {
void (*add_line_ptr)(struct line*, int x, int y);
int x;
int y;
};
void add_line(struct line* lptr, int x, int y)
{
lptr->x = x;
lptr->y = y;
}
int main()
{
struct line line1 = {add_line, 0, 0};
line1.add_line_ptr(&line1, 10, 20);
printf("%d %d\n", line1.x, line1.y);
}
I think that using line1.add_line(&line1, is a bit redundant - since it's quite obvious that I want to do the operation on line1.
Is there a way to implement this without passing a pointer to the "object"(struct)? or some other way I didn't think of?
Using function pointers just for the sake of emulating C++-like syntax is just messy with no obvious benefits. You won't have RAII in C no matter what you do, so you need to call constructors/destructors explicitly. If you do so by typing obj.foo() or obj = foo() has absolutely nothing to do with OO, it's mere coding style.
The main problem here though, is that your code does not have proper OO design, since the struct is completely open and not using private encapsulation. For the same reason as class line { public: int x; int y; }; is not proper OO either - you don't get OO just because you smash some related variables into an aggregate type, regardless of language.
"Cleanest"/"prettiest" would mean full private encapsulation. In C, that can be achieved with opaque types. I prefer to implement them without hiding pointers behind typedef, so:
line.h
#include <stdio.h>
#include <stdlib.h>
typedef struct line line; // forward declaration of incomplete type
line* line_construct (int x, int y);
line.c
#include "line.h"
struct line { // actual definition of the struct, local to line.c
int x; // private variable
int y; // private variable
};
line* line_construct (int x, int y)
{
line* obj = malloc (sizeof *obj);
if(obj == NULL) { /* error handling here */ }
obj->x = x;
obj->y = y;
return obj;
}
caller.c
#include "line.h"
int main(void)
{
line* x = line_construct(10, 20);
}
Here line is 100% encapsulated and the contents of the struct cannot be accessed by the caller. Since I don't hide pointers behind typedef, the caller must always use line* pointers and can never declare an instance of the object directly.
If the constructor is only meant to zero-out the struct members, then it doesn't need to get passed any parameters but can do so internally.
And obviously you need to implement a corresponding destructor with free as well.
line* line_destruct(line* obj) { free(obj); return NULL; } or so.
I wouldn't put the initializer into your structure to begin with. Other functions, sure, but not the first one. Something like this:
#include <stdio.h>
struct line {
int x;
int y;
};
void add_line(struct line *lptr, int x, int y)
{
lptr->x = x;
lptr->y = y;
}
int main()
{
struct line line1 = {0, 0};
add_line(&line1, 10, 20);
printf("%d %d\n", line1.x, line1.y);
}
The reason is that you have to assign the initializer anyway after you allocate your structure, either implicitly or explicitly. In OOP languages you normally name the class you want once, and both the allocator and initializer will run. In C you have to run them separately. Whether you allocate an object on the stack or on the heap, you will have to explicitly name the function you want to call at least once anyway.
Is there a way to get a pointer to an anonymous struct? With out anonymous structs I could write the following:
struct a{
int z;
};
struct b{
int y;
struct a *x;
}
This works fine, but I only use struct a within struct b and it seems redundant to pollute the global namespace with it. Is there a way I could define a pointer (x) to an anonymous struct. Something that would probably look like the following:
struct b{
int y;
struct {
int z;
} *x;
}
Or is this valid on its own?
Yes you can do this. But there is a complication: there is no way to directly declare another pointer to same type - or an object of that type, because... the struct type is anonymous.
It is still possible to use it however, by allocating memory for it with malloc, as conversions from void * to any pointer to object are possible without an explicit cast:
struct b {
int y;
struct {
int z;
} *x;
} y;
y.x = malloc(sizeof *y.x * 5);
Why would you think that this is better than polluting the namespace is beyond my imagination.
GCC provides the typeof so you can increase insanity by things like
typeof(y.x) foo;
or even declare a structure of that type
struct b y;
typeof(y.x[0]) foo;
foo.z = 42;
y.x = &foo;
error: must use "struct" tag to refer to type 'point'
All I want to do is store a coordinate as a struct.
This seems maddeningly simple to do but yet I cannot do it after visiting 20 websites and scouring Kernaghan's book.
What am I missing?
#include <stdio.h>
int main()
{
struct point
{
float x;
float y;
};
point.x = 0.0;
point.y = 1.9;
return 0;
}
You defined a type called struct point, not a variable name using that definition. You'd want to either define an instance of the struct using that type:
struct point mypoint; // In C, you could change mypoint to point, but that gets confusing
or (less common) declare variables with a type of the (possibly anonymous) struct definition by putting the name after the struct definition, before the semi-colon:
struct {
float x;
float y;
} point;
All you've declared is a type named struct point ; you haven't created an object named point to manipulate. You need a separate object definition, either by writing:
struct point {
float x;
float y;
};
struct point pvar;
or
struct point {
float x;
float y;
} pvar;
then you can manipulate the members of the object:
pvar.x = 0.0;
pvar.y = 1.9;
etc.
The "point" in your example is a struct tag, not a variable name. You have declared a type named struct point, but not any variable having that type. Where that declaration is in scope, you can declare variables having that type with the form
struct point my_point;
and then assign to their members as
my_point.x = 0.0;
my_point.y = 1.9;
What you have done, is similar to saying int = 3; This is more like it:
#include<stdio.h>
int main(void) {
struct point {
float x;
float y;
} s;
s.x = 0.0;
s.y = 1.9;
return 0;
}
But you should see compiler warnings, because the code assigns double values to float. It is better not to use the inferior float type unless you are forced to.
You need to have a structure object, ie instantiate the structure.
struct point obj;
obj.x = 0.0;
obj.y = 1.9;
Other options available are
struct point // Note,structure is tagged 'point' which enables multiple instantiations
{
float x;
float y;
}obj;
and
struct // Anonymous structure with one & only one instance possible
{
float x;
float y;
}obj;
and finally a typedef which is also a common practice
typedef struct point
{
float x;
float y;
}point;
point obj;
obj.x = 0.0;
obj.y = 1.9;
Let's say I have this struct in ANSI C:
typedef struct _point
{
float x;
float y;
} Point;
and this function to create this struct:
Point createpoint(float x, float y)
{
Point p;
p.x = x;
p.y = y;
return p;
}
This allows me to create a struct with this function i.e:
int main()
{
Point pointOne = createpoint(5, 6);
Point pointTwo = createpoint(10, 4);
float distance = calculatedistancefunc(pointOne, pointTwo);
/* ...other stuff */
return 0;
}
Someone told me that this code is not valid, because the struct does not get malloc'd in the createpoint(float x, float y) function before it gets returned, and that the struct will be deleted.
However, when I use my struct like this, it doesn't seem to get deleted.
So my question is:
do I have to malloc this struct, and why? / why not?
Whatever you are doing is entirely correct. The statement -
return p;
in the function returns a copy of the local variable p. But if you want the same object that was created in the function, then you need to malloc it. However, you need to free it later.
Point createpoint(float x, float y)
{
Point p;
p.x = x;
p.y = y;
return p;
} // p is no longer valid from this point. So, what you are returning is a copy of it.
But -
Point* createpoint(float x, float y)
{
Point *p = malloc(sizeof(Point));
p->x = x;
p->y = y;
return p;
}// Now you return the object that p is pointing to.
You can return struct on the stack, your code is valid. A problem would occur if you'd to return a pointer to the local variable, but that's not what you're doing, you're returning a copy, that's fine.
C99 allows for even nicer on-the-stack creation of structs.
Given the below struct
typedef struct
{
float x;
float y;
} Point;
you can initialize it in a bit of a C++ constructor style manner with the following statement:
Point p = (Point){0.4, 0.5};
and thus you could either shorten your createpoint or scrap it altogether:
int main()
{
Point pointOne = (Point){5, 6};
Point pointTwo = (Point){10, 4};
float distance = calculatedistancefunc(pointOne, pointTwo);
//...other stuff
return 0;
}
Point createpoint(float x, float y)
{
Point p;
p.x = x;
p.y = y;
return p;
} /
All local variables in function are deleted after function returns.
1> pass by reference
So if you are returning pointer to this local variable then after function return this variables are deleted so that pointers are invalid.
2> pass by value
But here you are returning copy of this local variable so its safe because that local variable are gona dead when function returns but the copy of return value will be stored in receiver variable in function call before function return.
A call to a method which returns a structure will behave as though the caller creates a temporary variable of the structure type somewhere which isn't visible in any other scope, and gives the called function a pointer to it. The called function will then put the data in the requested place, and after it returns the caller will be able to read the data from its new variable. Given a function and calling code:
StructType BuildStruct(void)
{
StructType it;
it.this=4;
it.that=23;
return it;
}
StructType myStruct;
myStruct = BuildStruct();
it's likely that there will be at least one copy operation if not two; the statement return it; may need to copy from local variable it to the temporary struct, and the assignment to myStruct may need to copy from the temporary location to myStruct. No situation actually requires two copy operations; some require one (which could be performed by the caller or by the called method) and some require none, but the necessity of copying is dependent upon details in both the caller and the called method.
An alternative design would be:
void BuildStruct(StructType *it)
{
it->this=4;
it->that=23;
}
StructType myStruct;
BuildStruct(&myStruct);
That would likely yield code equivalent to the best code one could hope for using a structure-type return variable, since the struct data would be placed directly into its final spot without any structure copying being necessary.