Is there a way to find the packed size of a structure defined and declared without packed attribute in GCC compiler?
Example:
struct Name
{
int a;
char ch;
}
any function or macro like get_packed_size(Name) should return 5
Define your struct using a macro that provides the required information. For example (though there are other possible implementations):
#define DEFINE_STRUCT_WITH_KNOWN_PACKED_SIZE(StructName, StructBody)\
struct StructName StructBody\
struct __attribute__ ((__packed__)) StructName##_packed StructBody
#define GET_PACKED_SIZE(StructName) sizeof (struct StructName##_packed)
DEFINE_STRUCT_WITH_KNOWN_PACKED_SIZE(Name, {
int a;
char ch;
};)
#include <stdio.h>
int main() {
printf("%lu", GET_PACKED_SIZE(Name));
}
No, there's no way... you only have sizeof(), and you need to take care of the padding...
Related
Is there a way of knowing the type of a struct member at compile time? Something analogous to offsetof(), but for types.
Eg. something like:
typedef struct{
int b;
char c;
}a_t;
typeof(a_t,b) a_get_b(void* data){
return *(typeof(a_t,b)*)(data + offsetof(a_t,b));
}
If you're willing to use typeof (which is currently a very common nonstandard C extension slated for inclusion in the next version of the standard), you can apply it to a member obtained from a compound literal as in typeof((a_t){0}.b):
typedef struct{ int b; char c; }a_t;
typeof((a_t){0}.b) a_get_b(void* data){ return (a_t*){data}->b; }
(Given a type a_t, (a_t){0} is a reliable way to get an instance of it. Because of how initialization works in C, the 0 will initialize a deepest first elementary member and elementary types are scalars and therefore 0-initializable.)
As for the obtaining the member from a void pointer pointing to the container, you could do:
*(typeof(&(a_t){0}.b)((char*)data + offsetof(a_t,b))
but that's just an awfully long-winded way to do:
(a_t*){data}->b
(which is 100% equivalent to the former as long as the effective type of data is indeed a_t*).
Another way it works:
#include <stdio.h>
#define typeof_element(_struct,el) typeof(((_struct *)(0))->el)
typedef struct{
int a;
int b;
}Row;
int main()
{
typeof_element(Row, a) value_a = 10;
printf("%d\n", value_a);
return 0;
}
Another way (other than Jerry Jeremiah's) is:
#define struct_get(STRUCT,ELEM) *(typeof(STRUCT.ELEM)*) (STRUCT+offsetof(typeof(STRUCT),ELEM))
I am trying to create a struct that I will use in a function via pointers. The issue is that I do not want to use global variables therefore I can't use a pointer to a struct as a parameter for the function prototype if I try to define the struct in main file, since it has not been defined yet.
How would I go about doing this? What I think the solution is, is to define the struct in a header file, then create local variables of that type in the main file. Is this the right way to go about this? Would appreciate some info about what i'm actually doing here if this is correct.
Sorry if I did anything wrong when posting, Its my first time.
Example of what I am thinking the solution is
Main.h
#include <stdio.h>
typedef struct Vehicle{
int a;
char b;
};
function(Vehicle *p);
Main.c
#include "Main.h"
Vehicle Car1;
Vehicle *p=&Car1;
function(p);
The proper syntax for a typedef is
typedef T-IDENTIFIER IDENTIFIER-LIST;
wherein the comma separated identifiers listed in IDENTIFIER-LIST become aliases for T-IDENTIFIER. A lot of the time IDENTIFIER-LIST will consist of a single identifier.
For example, in
typedef int integer, number;
integer and number are now type aliases for int.
When it comes to using typedef with structs, the form
typedef struct foo { /* ... */ } foo_type;
is more or less shorthand for
typedef struct foo foo_type;
struct foo { /* ... */ };
but does allow you to typedef an anonymous struct
typedef struct { /* ... */ } foo_type;
With all that said, in your code you have omitted the IDENTIFIER-LIST from your typedef.
If main.c really does consist entirely of the code you've posted, it will not compile. Every C program needs an entry point, and in a hosted environment that is the function main with the signature int main(void) or int main(int argc, char **argv).
While you can declare variables outside of functions (i.e., globals), you can not call functions from outside of functions. Everything starts from main.
A working example program:
main.h:
typedef struct {
int a;
char b;
} Vehicle;
void function(Vehicle *p);
main.c:
#include <stdio.h>
#include "main.h"
int main(void) {
Vehicle car = { 51, 'A' };
function(&car);
}
void function(Vehicle *v) {
printf("Vehicle: a: %d, b: %c\n", v->a, v->b);
}
I can't use the struct as a parameter for the function prototype
You misunderstood something.
Your typedef is rather useless.
You of course can use pointers to structs as function parameters and in the function prototypes.
typedef struct {
int a;
char b;
} Vehicle;
int foo(Vehicle *); // prototype
You can't call function not outside other functions (as it is shown in the main.c
Hi I was triying to make something like this, but I cant sort it out. The problem is one typedef needs the other one. I would really appreciate someones help!
#ifndef SHELL_DATA_H
#define SHELL_DATA_H
#include <buffer.h>
#define COMMANDS 10
#define MAX_ARGS 4
typedef struct {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
} t_command;
typedef struct {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
} t_shellData;
#endif
typedef struct command t_command;
typedef struct shelldata t_shellData;
struct command {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
};
struct shelldata {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
};
should fix it up for you. The structure tag and typedef name can be the same; I just renamed them for clarity.
C is a simple language, with an underlying principle of do not surprise people. For this reason, entities in C need to be declared or defined before they are used. As a simple example:
int f() {
int a = 7;
int b = a;
....
}
is OK, but this is not:
int f() {
int b = a;
int a = 7;
....
}
and while not exactly, languages like golang permit this -- the compiler will root around and find the definition you obviously wanted.
Typedef, in C, really just puts an entry into the symbol table; it is like a define, but less blunt, so the line:
typedef struct a A;
Serves to inform the compiler of two things: somewhere there is a structure with tag a, and I want A to be a shortform for it. There is another form of this:
struct a;
typedef struct a A;
Here, the first line tells the compiler "I want you to know about a thing called struct a"; and the second line "I want an alias to that struct a thing called A".
So, as the compiler progresses through the source, it knows that an A means a struct a, and even if it hasn't seen the definition of struct a, it has a placeholder.
But, if you attempted, before defining struct a to define another structure:
struct b {
struct a stuff;
int morestuff;
};
The compiler would complain, because it doesn't know the layout of a struct a; however this:
struct b {
struct a *stuff;
int morestuff;
};
is OK, because it knows how big a pointer is, and can defer its understanding of a struct a until it needs it.
So, Summary: declare or define data types before you attempt to use them. The C compiler requires it. A declaration is ok, unless you need the actual layout of it, in which case a definition is required.
Good Luck.
I'm trying to allocate dynamically a global struct in c, but something makes my c file not being able to find the reference to the extern variable.
The log:
main.c:18: undefined reference to `gate_array'
extern.h
#ifndef EXTERN_H_
#define EXTERN_H_
typedef struct gate_struct {
int out;
} gate;
extern gate *gate_array;
#endif /* EXTERN_H_ */
main.c:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "extern.h"
int main(int argc, char *argv[]){
gate_array = (gate*) malloc (2* sizeof(gate));
return 0;
}
Thanks!
There is no definition of gate_array due to extern. In this case, you can just remove the extern qualifier. However, if extern.h was used in multiple translation units (#include in several .c files) then this approach would result in multiple definition errors. Consider adding another .c file that would contain the definiton of gate_array (and any future variables), ensuring there is exactly one definition of gate_array.
The extern gate *gate_array tells the compiler that there is a variable called gate_array, but it is defined somewhere else. But there is no definition of gate_array in the posted code.
Also, you may wish to read
Do I cast the result of malloc?
This is probably what you meant to do:
#ifndef EXTERN_H_
#define EXTERN_H_
typedef struct gate_struct {
int out;
} gate;
typedef gate *gate_array;
#endif /* EXTERN_H_ */
This typedefs gate * to gate_array. Then in your main.c you want to do:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "extern.h"
int main(int argc, char *argv[]){
gate_array name_of_array = malloc (2* sizeof(gate));
free(name_of_array);
return 0;
}
Previously you were missing a variable name. Furthermore, it is bad practice to cast the return of malloc.
Pointer to gate i.e. gate_array was typedef not declared so you were doing something like this:
typedef int *IXX;
IXX = (int*) malloc(2*sizeof(int));
Do something like this:
IXX ix = (int*) malloc(2*sizeof(int));
Greeting,
I faced the error of "Assignment_1.c:10:18: error: storage size of ‘s’ isn’t known" I am not expert in using pointer to pointer, I want to have a dynamic sized array of dynamic sized words. Any idea?
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int size = MAX;
typedef struct{
int numberOfWords,averageWordLength,id;
char ** words;
}sentence;
void main(){
struct sentence s;
s.numberOfWords=3;
s.averageWordLength=5;
s.id=1;
s->words= malloc(size * sizeof(s));
//printf("%s",s.words);
}
Do not use typedef for structs unless you are trying to create an opaque type. This is wrong. struct is a great hint to C developers. Linus had a good description of this:
It's a mistake to use typedef for structures and pointers. When you
see a
vps_t a;
in the source, what does it mean?
In contrast, if it says
struct virtual_container *a;
you can actually tell what "a" is.
Lots of people think that typedefs "help readability". Not so. They
are useful only for:
(a) totally opaque objects (where the typedef is actively used to
hide
what the object is).
Example: "pte_t" etc. opaque objects that you can only access using
the proper accessor functions.
NOTE! Opaqueness and "accessor functions" are not good in themselves.
The reason we have them for things like pte_t etc. is that there
really is absolutely _zero_ portably accessible information there.
(b) Clear integer types, where the abstraction helps avoid
confusion
whether it is "int" or "long".
u8/u16/u32 are perfectly fine typedefs, although they fit into
category (d) better than here.
NOTE! Again - there needs to be a _reason_ for this. If something is
"unsigned long", then there's no reason to do
typedef unsigned long myflags_t;
but if there is a clear reason for why it under certain circumstances
might be an "unsigned int" and under other configurations might be
"unsigned long", then by all means go ahead and use a typedef.
(c) when you use sparse to literally create a new type for
type-checking.
...
Do not declare a bunch of variables in a row. You only confuse others by doing that.
And of course you cannot refer to a member field using . operator, you have to use ->. That being said, you code should look something like:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
struct sentence {
int numberOfWords;
int averageWordLength;
int id;
char **words;
};
int main()
{
struct sentence s;
s.numberOfWords = 3;
s.averageWordLength = 5;
s.id = 1;
s.words = malloc(MAX * sizeof(s));
/* printf("%s",s.words); */
return EXIT_SUCCESS;
}
Also consider having `words as the first member of the structure or you waste memory due to misalignment on platforms where alignment of a pointer is greater than integer.
Use '->' when the structure's object is a pointer type. This should work:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int size = MAX;
typedef struct{
int numberOfWords,averageWordLength,id;
char *words;
}sentence;
void main(){
sentence s;
s.numberOfWords=3;
s.averageWordLength=5;
s.id=1;
s.words= malloc(size * sizeof(s));
//printf("%s",s.words);
}
In
typedef struct {
int numberOfWords, averageWordLength, id;
char **words;
} sentence;
you create a unnamed struct and an alias for that struct. The alias name is sentence.
You now have a new type in your code. The new type name is sentence. If you provided a tag there would be 2 new type names: sentence and struct tag.
typedef struct tag {
whatever;
} sentence;
Also note the typedef isn't really needed
struct tag {
whatever;
};
The snippet above defines a new type named struct tag.