Size of struct members - c

I have a struct like
struct T {
int first, int second
} Tstruct;
now i want to define somewhere
pointer = struct.base + sizeof(Tstruct.second);
but i get error telling me put ")" befor "." , what is my mistake here? Sizeof(Tstruct) is working... Thanks.

From what I see in your question you might want the offsetof macro that is guaranteed to exist.
char* pointer = (void*)&Tstruct;
pointer += offsetof(struct T, second);
It also has the advantage to take care of possible padding between the fields.
If you really want to do what you say in your question, if you have C99 you can use a compound literal:
pointer += sizeof ((const struct T){ 0 }).second;
here ((const struct T){ 0 }) is a temporary of the struct type, but who's creation will be optimized out by any C99 conforming compiler without problems.

You can't do that, but you can use sizeof(int) or even sizeof(struct.second) (assuming struct is an instance of struct T with an illegal name).
sizeof operates on both types and expressions. sizeof(Tstruct.second) is neither a type nor a valid expression. However, given a valid instance of Tstruct the following is an expression whose type is the type of Tstruct::second:
Tstruct properly_named_struct;
sizeof(properly_named_struct.second);

sizeof ( TStruct.second ) is perfectly valid.
struct.base isn't because struct is a reserved keyword in C and should point to the member name of the structure.

Related

Using sizeof() with pointer to struct in C

I'm learning C right now and came to a little problem I encountered while trying out some code snippets from my uni course.
It's about typedef'd pointers to structs and their usage in the sizeof() function.
#include <stdio.h>
#include <stdlib.h>
// Define struct
struct IntArrayStruct
{
int length;
int *array;
};
// Set typedef for pointer to struct
typedef struct IntArrayStruct *IntArrayRef;
// Declare function makeArray()
IntArrayRef makeArray(int length);
// Main function
int main(void)
{
// Use makeArray() to create a new array
int arraySize = 30;
IntArrayRef newArray = makeArray(arraySize);
}
// Define makeArray() with function body
IntArrayRef makeArray(int length)
{
IntArrayRef newArray = malloc(sizeof(*IntArrayRef)); // ERROR
newArray->length = length;
newArray->array = malloc(length * sizeof(int));
return newArray;
}
And the code really works in the IDE used in class (Virtual C), but when I try the exact same example in VSCode and compile it using GNU Make or GCC, it returns an error because sizeof(*IntArrayRef) in the malloc() function call is marked as an unexpected type name.
error: unexpected type name 'IntArrayRef': expected expression
However, when I change it to sizeof(IntArrayStruct), everything works splendidly.
Isn't *IntArrayRef the same value as IntArrayStruct?
IntArrayRef is the name of a type, therefore *IntArrayRef is invalid syntax. What you can (and should) do instead is give the name of the variable and dereference that:
IntArrayRef newArray = malloc(sizeof(*newArray));
Here's how your type names relate to each other:
struct IntArrayStruct * == IntArrayRef
Thus, newArray has type IntArrayRef which is the same as struct IntArrayStruct *
So, if you want the size of the pointer type, you'd use one of
sizeof (IntArrayRef)
sizeof (struct IntArrayStruct *)
sizeof newArray
If you want the size of the pointed-to type (the actual struct type), you'd use one of
sizeof (struct IntArrayStruct)
sizeof *newArray
sizeof is an operator, not a function - parentheses are only required if the operand is a type name (including typedef names). It doesn't hurt to use parentheses around non-type operands like sizeof (*newArray), but they're not necessary.
As a stylistic note, it's generally a bad idea to hide pointer types behind typedefs, especially if the user of the type has to know it's a pointer type to use it correctly. IOW, if the user of the type ever has to dereference something, then the pointerness of that something should be explicit. Even if the user doesn't need ever need to explicitly dereference it, you still shouldn't hide the pointerness of the type (take the FILE * type in the standard library as an example - you never actually dereference a FILE * object, but its pointerness is still made explicit).
Otherwise, be prepared to write a full API that hides all pointer operations from the user.
Compare
sizeof(IntArrayStruct*)
sizeof(IntArrayRef)
vs
sizeof(IntArrayStruct)
The first two are the same, and they are the size of just the pointer. I.e. same as sizeof(int*), sizeof(long*), sizeof(void*) etc.
The third is the size of the actual data structure. That's what you want if you are creating space for it with malloc.
Also Pointers and References are two different things in C++ , so it might be less confusing to communicate the fact that something is a pointers, with the abbreviation "ptr".
Finally, as mentioned, the creating a new type name, just to represent a pointer to a struct type, is non-standard. It would confuse other people without much benefit.

What does this pointer of type structure definition mean (in C)?

In K&R Chapter 6, a declaration is mentioned as follows:
struct{
int len;
char *str;
} *p;
I couldn't understand which structure is this pointer p pointing to and if such a pointer definition is even valid because in all other examples given in the book and the ones I have seen otherwise, when defining a pointer to a structure, the name of the structure, that is, the type being defined needs to be mentioned. For example,
struct example{
int a;
...
}s1;
and then,
struct example *ptr = &s1;
so, it is mentioned that ptr is pointing to a type struct example and not just struct.
Also, of particular interest was this:
*p->str fetches whatever str points to; *p->str++
increments str after accessing whatever it points to (just like *s++);
I couldn't follow what p is in the first place, hence, not the increment and dereference as well.
What is going on here?
Thanks in advance!
P.S. I am new here, so any feedback on the format of the question would also be appreciated.
The struct keyword works sort of like an extended version of typedef, except that you create a complex custom type (called a structure) instead of aliasing an existing type. If you only have one thing that needs to use the declared type, you do not need to provide an explicit name for the type.
The first statement you are looking at declares a structure with two fields, but does not name it. This is called an anonymous structure. The declaration does, however, provide a pointer of that type.
One possible use-case for such a declaration is when you make a header for an external library, possibly one that is not even written in C. In that case, the type of the structure may be opaque or incomplete, and you just need to have a convenient reference to some parts of it. Making the structure anonymous prevents you from being able to allocate it yourself easily, but allows you to interact with it through the pointer.
More commonly, you will see this notation used in conjunction with named or at least aliased structures. The second statement could be rewritten as
struct example { ... } s1, *ptr;
In that case, struct example *ptr = &s1; would be just ptr = &s1;.
An even more common occurrence is the use of anonymous structures with typedef, create custom type names that do not include the struct keyword. Your second example could be rewritten as
typedef struct { ... } example, *pexample;
example s1;
pexample ptr; // alternatively example *ptr;
ptr = &s1;
Note that the type of s1 is example and not struct example in this case.
For starters consider the following simple program
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
struct {
int len;
char *str;
} *p;
p = malloc( sizeof( *p ) );
p->str = "Hello Nihal Jain";
p->len = strlen( p->str );
while ( *p->str ) putchar( *p->str++ );
putchar( '\n' );
free( p );
return 0;
}
Its output is
Hello Nihal Jain
So in this declaration
struct {
int len;
char *str;
} *p;
there is declared a pointer of the type of the unnamed structure. The pointer itself is not initialized. You could write for example
struct {
int len;
char *str;
} *p = malloc( sizeof( *p ) );
For this simple program the name of the structure is not required because neither declaration of an object of the structure type is present or needed in the program.
So you can not declare an object of the structure type but it is not required in this case.
According to the C Standard structure or union are declared like
struct-or-union-specifier:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
It is seen that the identifier is optional if there is a struct-declaration-list. So an unnamed structure can be used as a type specifier.
One more example with using enumerations. You can declare enumerators without declaring the enumeration type. For example
enum { EXIT_SUCCESS = 0, EXIT_FAILURE = -1 };
You can use the enumerators that have the type int without declaring an object of the enumeration type if there is no such a requirement in the program.
Also another use (of anonymous structures) would be to use them inside unions or other structs which basically limits the use of that struct to that particular parents union or structure not anything else, which is quite useful from programmer's point of view because looking at a code like this it provides us with the information that it is used locally on the context of the struct or union inside it -
nothing more than that. (also saves us from naming).
Also if you use this anonymous structure you wont be able to allocate one instance of it other than the one which already exists.
Example:-(stark's comment: how to use it?)
struct {
int a;
int b;
} p;
scanf("%d",&p.a);
If you needed an ad-hoc, one-time-use definition of a struct (or union) that will not be useful outside of scope in which it was declared, you would use what is called anonymous or unnamed structs and unions. This saves you from having to declare the struct before you use it and, in the case of complex types, declaring the inner types, such as here.

Dereferencing pointer type when in sizeof()

I have following structure:
typedef struct _foo_t {
int bar;
float buzz;
char quux[40];
} *const foo_t;
Is there a way to get the size of structure, like it's done via sizeof(struct _foo_t), but using only name foo_t? I have tried sizeof(*foo_t), but that does not compile.
I don't believe you can do this directly. You'll need to define an intermediate typedef if you want to do this:
typedef struct _foo_t {
int bar;
float buzz;
char quux[40];
} foo_t;
typedef foo_t *const foo_tp;
// sizeof(foo_t) should work
Dereferencing a type doesn't really make sense in C. You can dereference a variable, but not a type. In C++, you can do these kinds of type operations using templates, but that's not really applicable since you indicate the C tag.
You could also declare a dummy variable of the appropriate type to invoke sizeof on an expression:
foo_tp f;
// sizeof(*f) should work
You can accomplish this by using a compound literal like this:
sizeof(*(foo_t){NULL})
foo_t is a typedef, so it is like a type.
*foo_t is not a valid expression, because you cannot dereference a type.
Since it is not a valid expression, you cannot get its size.
It is as writing:
typedef int * pointer_to_int_type;
size_t a = sizeof(*pointer_to_int_type);
You cannot use a type name as an operand (not only for sizeof), as an expression requires to have a type (in C, types are no first class citizens like in full OO-languages like Python). However, you can use a type-name alone when using the parenthesized version - C11 draft 6.5.3.4#1/2. An understandable restriction.
Note that an expression in parenthesis after the sizeof keyword would have different gramatical semantics: the parenthesis are part of the expression, while for a type name, they are part of the sizeof operator (which would work like a function call). (I'm really not keen writing a parser for C myself.)
I for myself do normally not typedef pointers. That hides the semantics and supports forgetting about their somewhat special (and dangerous) properties. An exception would be an external interface where the pointer is externally used more like a handle than a pointer. But this I really only use at the outer membrane.
Ok, as I got from the discussion, you are trying to work with opaque pointers. But that will not work by defining the struct type and the pointer at once anyway. You will need to split that:
"hidden_stuff.h":
typedef struct HiddenStruct * const HiddenStructHandle;
"hidden_stuff.c"
#include "hidden_stuff.h"
struct HiddenStruct {
...
};
Having the struct in the header will break the encapsulation/hiding.

nested struct in C

struct s{
int a;
struct s b;
};
The above code segment throws the error error: field 'b' has incomplete type while
struct s{
int a;
struct s *b;
};
doesn't give any error. I don't understand why this is allowed for pointers but not for the non-pointer variable !!
Class members must have a complete type when they are declared, so that their size can be used to determine the class layout.
Within the class definition, the class itself is incomplete, so you can't declare a member of the same type. That would be impossible anyway (at least if there are any other members), since the class would have to be larger than itself.
A pointer is a complete type, even if the type it points to isn't, so you can declare a class member to be a pointer to the class type.
(Note: I use the word "class" since I'm a C++ programmer. I just noticed that the question is also tagged C, and C++ has since been removed. I believe the answer is still correct in that language, if you replace "class" with "structure", but I'm not completely sure since they are different languages. It would be better if you only asked about one language, since there are differences (sometimes major, sometimes subtle) between languages.)
Q: What are incomplete types?
A: An incomplete type is a type which has the identifier but lacks information needed to determine the size of the identifier.
The ‘void’ type is an incomplete type.
A union/structure type whose members which are not yet specified.
‘void’ type cannot be completed.
To complete an incomplete type, we need to specify the missing
information.
Example:
struct Employee *ptr; // Here 'Employee' is incomplete
C/C++ allows pointers to incomplete types.
To make 'Employee' complete, we need to specify missing information like shown below
typedef struct Employee
{
char name[25];
int age;
int employeeID;
char department[25];
}EMP;
In your case,
struct s
{
int a;
struct s b; // Structure is incomplete.
}// Till this point the structure is incomplete.
The struct s b; the structure s is incomplete. We can declare a pointer to incomplete type not a variable.
To adequately define s, the compiler needs to know the size of s. In the first example, the size of s depends on the size of s, but not in the second.
In the first example, by defintion, sizeof(s) = sizeof(int) + sizeof(s) + padding. If we try to solve this equation for sizeof(s), we get 0 = sizeof(int) + padding, which clearly is impossible.
In the second, sizeof(s) = sizeof(int) + sizeof(s*) + padding. If we assume that sizeof(s*) ~= sizeof(int), then sizeof(s) = 2*sizeof(int) + padding.
I'm going to assume that the extra asterisks in struct s **b** are given for emphasis and not as some kind of demented pointer declaration. (Please don't do that! It's much easier to analyze someone's code if it's presented exactly as it runs.)
When you do this without declaring b as a pointer:
struct s{
int a;
struct s b;
};
the compiler doesn't know how much space it needs to allocate for the b field, since at that point you haven't finished defining struct s. In fact, it would be impossible for the compiler to define this particular structure: no matter how many bytes it allocated for struct s, it would have to add 4 more to make room for the int a field.
Declaring b to be a pointer to struct s makes things easier:
struct s{
int a;
struct s *b;
};
No matter how many fields you add to struct s, the compiler knows that the b field only needs to contain the address of the struct, and that doesn't change based on how large the struct itself it.

Why does a non-constant offsetof expression work?

Why does this work:
#include <sys/types.h>
#include <stdio.h>
#include <stddef.h>
typedef struct x {
int a;
int b[128];
} x_t;
int function(int i)
{
size_t a;
a = offsetof(x_t, b[i]);
return a;
}
int main(int argc, char **argv)
{
printf("%d\n", function(atoi(argv[1])));
}
If I remember the definition of offsetof correctly, it's a compile time construct. Using 'i' as the array index results in a non-constant expression. I don't understand how the compiler can evaluate the expression at compile time.
Why isn't this flagged as an error?
The C standard does not require this to work, but it likely works in some C implementations because offsetof(type, member) expands to something like:
type t; // Declare an object of type "type".
char *start = (char *) &t; // Find starting address of object.
char *p = (char *) &t->member; // Find address of member.
p - start; // Evaluate offset from start to member.
I have separated the above into parts to display the essential logic. The actual implementation of offsetof would be different, possibly using implementation-dependent features, but the core idea is that the address of a fictitious or temporary object would be subtracted from the address of the member within the object, and this results in the offset. It is designed to work for members but, as an unintended effect, it also works (in some C implementations) for elements of arrays in structures.
It works for these elements simply because the construction used to find the address of a member also works to find the address of an element of an array member, and the subtraction of the pointers works in a natural way.
it's a compile time construct
AFAICS, there are no such constraints. All the standard says is:
[C99, 7.17]:
The macro...
offsetof(type, member-designator)
...
The type and member designator shall be such that given
static type t;
then the expression &(t.member-designator) evaluates to an address constant.
offsetof (type,member)
Return member offset: This macro with functional form returns the offset value in bytes of member member in the data structure or union type type.
http://www.cplusplus.com/reference/cstddef/offsetof/
(C, C++98 and C++11 standards)
I think I understand this now.
The offsetof() macro does not evaluate to a constant, it evaluates to a run-time expression that returns the offset. Thus as long as type.member is valid syntax, the compiler doesn't care what it is. You can use arbitrary expressions for the array index. I had thought it was like sizeof and had to be constant at compile time.
There has been some confusion on what exactly is permitted as a member-designator. Here are two papers I am aware of:
DR 496
Offsetof for Pointers to Members
However, even quite old versions of GCC, clang, and ICC support calculating array elements with dynamic offset. Based on Raymond's blog I guess that MSVC has long supported it too.
I believe it is based out of pragmatism. For those not familiar, the "struct hack" and flexible array members use variable-length data in the last member of a struct:
struct string {
size_t size;
const char data[];
};
This type is often allocated with something like this:
string *string_alloc(size_t size) {
string *s = malloc(offsetof(string, data[size]));
s->size = size;
return s;
}
Admittedly, this latter part is just a theory. It's such a useful optimization that I imagine that initially it was permitted on purpose for such cases, or it was accidentally supported and then found to be useful for exactly such cases.

Resources