what's the meaning of the '.' in the struct [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What means the dot before variable name in struct?
const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
// ....other stuffs
};
my question is :
1) what is the meaning of .llseek and how to use ....the file_operations struct definition is below:
2) can I just say : llseek = generic_file_llseek ; in the struct above to let the pointer llseek points to generic_file_llseek without putting the dot . before llseek?
//sorry for my poor english
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//....other stuffs
}

It's a special structure initialization syntax that has been introduced in c99.
When you have .llseek = generic_file_llseek, inside your structure initializer, this means you are initializing this particular member regardless of its offset relative to the structure beginning.
Alternatively you can use an initialization without designators, but you will have to put the initializers in the exact order as the corresponding fields in the structure are declared.
const struct file_operations generic_ro_fops = {
generic_file_llseek, // this initializes llseek member
do_sync_read, // this initializes read member
// ....other stuffs
};

This is called designated initializers. You are initializing exact member/field of the structure.
2.can i just say : "llseek = generic_file_llseek ;" in the struct above to let the pointer llseek points to generic_file_llseek without
putting the dot '.' before llseek?
No
You can do something like this to initialize members:
const struct file_operations generic_ro_fops = {
generic_file_llseek,
do_sync_read,
// ....other stuffs
};
but in this case you will have to initialize everything in order like members are placed inside structure. Designated initializers are very helpful when you want to initialize just some of structure fields.
You can use something like this outside structure:
generic_ro_fops.llseek = generic_file_llseek;

The meaning of the '.' in that struct is called a designated initializer. In the struct, each '.' represents member of the struct which needs to be initialized, thus being called a designator.

Meaning
1) what is the meaning of .llseek and how to use ....the file_operations struct definition is below:
It is a C99 feature: designated initializers. With the . you can initialize a given field of your structure. Here, it is necessary to initialize your structure cause of the const qualifier.
If lseek and read are in this order in the structure definition, you can ommit this designator.
const struct file_operations generic_ro_fops = {
generic_file_llseek,
do_sync_read
};
This last method is not very maintenable (if you change the order of your structure's fields, you have to change all your initialization code), therefore the method with designated iniitializers is better, here.
Other manner
2) can I just say : llseek = generic_file_llseek ; in the struct above to let the pointer llseek points to generic_file_llseek without putting the dot . before llseek? //sorry for my poor english
No, you can't, because it is not the right syntax.
References
C11 (n1570), § 6.7.9 Initialization
If a designator has the form
. identifier
then the current object (defined below) shall have structure or union
type and the identifier shall be the name of a member of that type.

Related

How to assign a struct member array using a struct pointer?

How to assign an array wrapped into a struct using the struct pointer?
I know this syntax:
size_t initArrayList[] = {1,1,1};
memcpy(pStruct->sizet, initArrayList, sizeof(pStruct->sizet));
is it possible to use a similar syntax as:
Stru = (struct myStruct) {.sizet = {1,1,1}};
using pointers?
I'd appreciate a detailed explanation of what (struct myStruct) {.sizet = {1,1,1}} does.
struct myStruct {
size_t sizet[3];
} ;
void struInit(struct myStruct * pStruct) ;
int main()
{
struct myStruct Stru;
struInit(&Stru);
if (Stru.sizet[1]==1)
printf("\nStru.sizet[1]==1");
return 0;
}
void struInit(struct myStruct * pStruct ) {
// I know this syntax
// size_t initArrayList[] = {1,1,1};
// memcpy(pStruct->sizet, initArrayList, sizeof(pStruct->sizet));
}
Either calling memcpy using a temporary array (just as commented out in your struInit function)
memcpy(pStruct->sizet, initArrayList, sizeof(pStruct->sizet));
or assigning to the pointed-to structure using a compound literal (notice the use of the * dereference operator)
*pStruct = (struct myStruct){.sizet={1,1,1}};
or even a conventional for-loop, copying element by element, does what you want.
Or if you can not rely on designated initializers or compound literals,
both being features that have only been standardized since C99, you can
use an equivalent, C89 way, that doesn't make use of them:
struct myStruct tmp = {{1,1,1}};
*pStruct = tmp;
I'd appreciate a detailed explanation of what (struct myStruct) {.sizet = {1,1,1}} does.
The relevant parts of C99 describing designated initializers and
compound literals are 6.7.8 Initialization and 6.5.2.5 Compound
literals.
The short answer is that if used in the struInit function it
constructs a local unnamed object with the type struct myStruct,
initializing its member sizet to {1,1,1}, this in turn being syntax
for array element initialization, assigning a value of 1 to its
elements [0], [1], and [2], in that exact order.

Initialize pointer to a struct with a compound literal

I'm new to C and I'm trying to understand the syntax for compound literals. My question is similar to Initializing a pointer to compound literals in C but I don't think that answers it. If have a struct and a type defined as a pointer to the struct like this:
typedef struct thing *thing_t;
struct thing
{
int id;
char *name;
};
Then I can create a thing_t like this:
thing_t instance = & (struct thing) {
.id = 1,
.name = "A"
};
I was wondering if there is a way to initialize a thing_t without explicitly referring to struct thing, e.g. I tried this to see if it was valid syntax:
thing_t instance = (* thing_t) {
.id = 1,
.name = "A"
};
but the compiler errors. The compiler must "know" that the thing_t type holds a pointer to a thing, but is there syntax that allows to use the two interchangably in this context?
(I don't have a particular use case for this, I'm just trying to understand how the type and the struct are related).
I was wondering if there is a way to initialize a thing_t without
explicitly referring to struct thing, e.g. I tried this to see if it
was valid syntax:
thing_t instance = (* thing_t) {
.id = 1,
.name = "A"
};
but the compiler errors. The compiler must "know" that the thing_t
type holds a pointer to a thing,
Yes, it does, though it is poor form to define a type alias that hides pointer nature, as you have done, and it is especially poor form to do so with a name that does not somehow provide a clue about that.
but is there syntax that allows to
use the two interchangably in this context?
The syntax for a compound literal includes the parenthesized type specifier. That's not a cast, it's part of the literal itself. You cannot do without it. If you want to avoid saying struct, though, then you can kill two birds with one stone by changing your type alias so that it describes the struct type itself, not a pointer to one:
typedef struct thing thing_t;
struct thing {
int id;
char *name;
};
thing_t *instance = & (thing_t) {
.id = 1,
.name = "A"
};
Not only does it work, but it's a heck of a lot clearer than your proposal. For example, the use of the & operator matches up with the clear declaration of variable instance as a pointer.

Use of struct initialization syntax for on-heap struct

I have this simple structure I want to initialize on the heap and return as a pointer in a function.
struct entry {
const char* const key; // We don't want the key modified in any way
const void* data; // But the pointer to data can change
struct entry* next;
};
There is one problem, I cannot calloc it and initialize members one by one because key is a const pointer. I found somewhere this syntax that works:
struct entry* entry = calloc(1, sizeof(struct entry));
*entry = (struct entry) { .key = key, .data = data, .next = NULL };
But I don't know what is going on with it: does it create an "anonymous" struct that is then copied to the place where *entry lives? Is that safe to use or should I prefer creating a local struct that is then copied with memcpy to the right location?
The assignment you presented is not correct and should not compile.
The correct way of initializing an allocated struct with const members is to allocate some memory, create a temporary struct entry object, and then use memcpy to copy the object to the allocated memory:
void* mem = malloc( sizeof( struct entry ) );
struct entry temp = { key , data , NULL };
memcpy( mem , &temp , sizeof( temp ) );
struct entry* e = mem;
This line:
*entry = (struct entry) { .key = key, .data = data, .next = NULL };
uses the assignment operator. The conditions for assignment operator (C11 6.5.16/2) include:
Constraints
An assignment operator shall have a modifiable lvalue as its left operand.
The definition of modifiable lvalue can be found in 6.3.2.1/1:
A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.
So *entry is not a modifiable lvalue, because its type is a struct that has a member with const-qualified type. Therefore it is a constraint violation to have *entry appear on the left-hand-side of the assignment operator.
The clang compiler (all versions I tried) appears to not give any diagnostic message for this constraint violation; this is clearly a compiler bug. gcc does give a diagnostic.
Regarding the second part of the question:
should I prefer creating a local struct that is then copied with memcpy to the right location?
As also explained by 2501, you can do this in C when writing into space allocated by the malloc family. (If you had declared a named struct entry object then it is less clear whether memcpying over it is permitted).

understanding fs/binfmt_elf.c

i am trying to understand the linux source file /home/akash/Downloads/linux-3.4.3/fs/binfmt_elf.c a part a code is as follows where i hv stuck.
static struct linux_binfmt elf_format = {
.module = THIS_MODULE,
.load_binary = load_elf_binary,
.load_shlib = load_elf_library,
.core_dump = elf_core_dump,
.min_coredump = ELF_EXEC_PAGESIZE,
};
which refer to the file include/linux/binfmt.h
struct linux_binfmt {
struct list_head lh;
struct module *module;
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(struct file *);
int (*core_dump)(struct coredump_params *cprm);
unsigned long min_coredump; /* minimal dump size */
};
plz giv some explaination on this..
It is the initialisation of a structure of type struct linux_binfmt named elf_format (with static storage duration, meaning it exists for the lifetime of the program and is initialised exactly once), using syntax introduced in C99 that allows the specific structure member being initialised to be specified. Prior to C99 the initializer of a struct required the values to be listed in the order the members are declared in the struct.
For example:
struct struct_a { int a; char c; };
In C89 it was not possible to explicitly initialise c only:
struct struct_a s = { 0, 'f' }; /* Have to provide an initial value for
'a', the 0, in order to provide an
initial value for 'c', the f. */
but in C99 the new syntax made it possible:
struct struct_a s = { .c = 'f' };
The types of struct members:
lh is of type struct list_head, which is not explicitly initialised. lh will be default initialised (any members of lh that are pointers are initialized to a null pointer and any arithmetic types will be initialized to zero).
module is of type struct module* and is initialised to THIS_MODULE.
load_binary is a pointer to a function that returns an int and takes arguments of type struct linux_binptrm* and struct pt_regs, and is initialised to a function called load_elf_binary.
load_shlib is a pointer to a function that returns an int and takes an argument of type struct file* and is initialised to a function called load_elf_library.
core_dump is a pointer to a function that returns an int and takes an argument of struct coredump_params* and is initialised to a function called elf_core_dump.
min_coredump is of type unsigned long and is initialised to ELF_EXEC_PAGESIZE.
Refer to section 6.7.8 Initialization of the C99 standard for a full description on initialization syntax and rules.
elf_format is a variable of type linux_binfmt declared as static.
Values assigned for the members of elf_format
.module = THIS_MODULE,
.load_binary = load_elf_binary, /* Function pointer assigned with functions */
.load_shlib = load_elf_library, // do --
.core_dump = elf_core_dump, // do --
.min_coredump = ELF_EXEC_PAGESIZE,

What does a dot before the variable name in struct mean?

looking at the linux kernel source, I found this:
static struct tty_operations serial_ops = {
.open = tiny_open,
.close = tiny_close,
.write = tiny_write,
.write_room = tiny_write_room,
.set_termios = tiny_set_termios,
};
I've never seen such a notation in C.
Why is there a dot before the variable name?
This is a Designated Initializer, which is syntax added for C99.
Relevant excerpt:
In a structure initializer, specify the name of a field to initialize
with ‘.fieldname =’ before the element value. For example, given the
following structure,
struct point { int x, y; };
the following initialization
struct point p = { .y = yvalue, .x = xvalue };
is equivalent to
struct point p = { xvalue, yvalue };
It's sometimes called "designated initialization". This is a C99 addition, though it's been a GNU extension for a while.
In the list, each . names a member of the struct to initialize, the so called designator.

Resources