use of static array to initialize constant struct object - c

I recently came across the following code:
static const struct gaih gaih[] = {
#if defined __UCLIBC_HAS_IPV6__
{ PF_INET6, gaih_inet },
#endif
{ PF_INET, gaih_inet },
#if 0
{ PF_LOCAL, gaih_local },
#endif
{ PF_UNSPEC, NULL }
};
struct gaih {
int family;
int (*gaih)(const char *name, const struct gaih_service *service,
const struct addrinfo *req, struct addrinfo **pai);
};
int func{
const struct gaih *g = gaih;
}
I understand the meaning of constant and static .
But I able to decipher the logic behind static initialization of the constant object in such a crude way.
please clarify the reason or use of doing it this way

file.c seems to be a C file. Using static in C has two meanings:
Not on the stack (e.g. for variables inside functions that shall keep their value across several calls of the function)
Not exported from this module (for variables that shall not be provided as a symbol to the linker)
In this case it seems to be the second one. The variable gaih shall not be exported (visible for the linker) static and it shall not be changed const. There is nothing crude.
But to clarify further details the complete valid code would be needed. It seems to be a constant and static initialisation of an array of structs with just one entry. The variable g is just a pointer to this single entry.
This example has some similarity with the struct gaih_addrtuple in nss.h which is a linked list of host names and IP addresses used for gethostbyname.

The global variable gaih is defined as static, which means it is only visible in the current file, and const, which means it can't be modified once initialized.
The local variable g is also defined as const, meaning it can't be changed. It is initialized with the address of the global gaih array, so g can be treated as an array in this context.
g can also be passed to another function, possibly in a different file. This allows the contents of gaih to be read outside of the current file which would not be allowed by attempting to reference gaih directly.

Related

How to use const pointers inside structures?

hope everyone is doing great!
I was trying to implement some lib in embbeded enviroment, where i need to use const pointers.
Here is the code i was trying to do:
#include <stdio.h>
int a = 10;
typedef struct {
void * const payload;
int size;
} msg;
typedef struct {
void * const payload2encode;
int size2encode;
} encode_msg;
msg message[1] = {
{
/* payload */ &a,
0
}
};
encode_msg encoded_message = {
/* payload */ message[0].payload,
0
};
int main(void){
return 0;
}
but i'm getting the following error:
main.c:23:19: error: initializer element is not constant 23 |
/* payload */ message[0].payload,
If I change 'message[0].payload' to '&a' the code runs fine. I don't get why this is happening :(. Anyone know why?
Best reggards!
There are a lot of misconceptions here.
First of all, why do you need a "constant pointer"? This message here:
error: initializer element is not constant
Does not mean "the compiler wants a constant pointer", but rather "I want a a compile-time constant such as an integer constant expression". This has nothing to do with const at all in C (C++ is another story), but this:
A variable with static storage duration, like one declared at file scope outside any function, must be initialized with a constant expression. Such as an integer constant expression or in case of pointers the address of another variable. But it cannot be initialized to the value of a different variable. Simple example:
int a = 0;
int b = a; // error: initializer element is not constant
That's just how the language works. You could initialize a pointer to an address however, since address constants are constant expressions. That's why /* payload */ &a, works.
Next misconception: there is nothing called "constant pointer". There are:
pointers to read-only data, const type* name.
read-only pointers to read/write data: type* const name.
read-only pointers to read-only data: const type* const name.
For some reason you picked the second of these options (took a gamble?). It has limited uses, but one valid use of it is to declare read-only pointer variables in ROM on embedded systems with true ROM like flash.
Also we usually don't want to use qualifiers like const inside a struct on an individual member if we can avoid it. Because then the struct variable itself ends up with different qualifiers than it's members. Normally we want the whole struct to be const or nothing in the struct at all. In embedded systems we also need to consider if we want it to be stored in RAM or flash.
Regarding void*, they are not very suitable to use for any purpose in an embedded system. uint8_t* boiling down to a character pointer is much more useful, since it can be used to access any other type byte by byte. Whereas a void* has to be converted to another type before we can do anything meaningful with it. Type-generic programming in embedded systems is also a bad idea most of the time, since such systems should behave deterministically.
encoded_message has static storage duration (because it's declared outside any function) and so must be initialized with a constant expression, and message[0].payload isn't (it's a const variable, but not a constant expression).
You can either declare encoded_message in a function (main, for instance), or, if your compiler supports it, make message const as well.
See also : Error "initializer element is not constant" when trying to initialize variable with const

why is not possible to have static members in struct?

First, from this:
static struct foo1 { //private struct, just for this file
int a;
};
int main (void) {
struct foo1 a = {10};
return 0;
}
question number 1
I will get warning:
warning: useless storage class specifier in empty declaration
};
What does it mean? Why is static "useless storage class specifier"? In other context (static local var in function, or global static, which I wanted to apply for the struct foo1, it would work).
question number 2
#include <stdbool.h>
static struct s_t{ //private struct (for this file only)
static bool is_there = false; // defaul (pre-defined) value for all instances
int value;
};
int main (void) {}
Why is not possible to have static, predefined value for all vars of type struct s_t in c? I just wanted to simulate the same functionality as is in function static local var -> preserve value across multiple calls, in that sense, I wanted have one member (bool is_there in this case) that preserve value across each var of type struct foo1 (instance of it). So why it is not possible?
question number 3
Also, can someone explain the error (in more general sense) from it:
error: expected specifier-qualifier-list before ‘static’
EDIT:
from comments, I do not really understand the concept of storage class, I know only from asm, there is data/text/bss segments, so does it mean static var has address in read-only part of memory? Or what is the concept of storage class in c related to asm?
Because static struct foo1 { ... is just a struct definition, not a variable. You should add static when you declare the instance of the struct. I prefer this style:
typedef struct {
int a;
}foo_t;
static foo_t a = {10};
Because C simply doesn't have static member variables like C++ does. In C, it's pretty useless to add storage- or type specifiers to a single struct member. Put it on the allocated variables instead.
TL;DR it's just not making any sense of your syntax since you can't have static there. Unless you are terribly interested about language grammar, there's nothing else to it.
static is a storage-class specifier and const etc are type qualifiers and int etc is a type specifier. The term specifier-qualifier list comes from formal C grammar of structs, which isn't terribly interesting to read unless you are making a compiler. When declaring a struct member you have two options (C17 6.7.2.1):
specifier-qualifier-list:
type-specifier specifier-qualifier-list(opt)
type-qualifier specifier-qualifier-list(opt)
static doesn't fit the bill of either, being a storage-class specifier, so the compiler is saying "what! this is not a specifier-qualifier list where I expected to find one, where is it?"
(And yeah it's recursive, so you can have multiple of type-specifier or type-qualifier such as const long const const int value;. Because C stands for Crazy.)
because struct is like a type or an object, when you declare a static member in C, it would be like:
static int a = 0;
In this case "int" is like the struct type you declared, so if you want to create a struct static member just do like this:
static s_t a;
static struct foo1 { //private struct, just for this file
int a;
};
The static declaration specifier only applies to object or function declarations, not type definitions. All you're doing in that statement is creating the struct foo1 type. Had you written something like
static struct foo1 {
int a;
} foo;
Then the object foo would be declared static.
If you declare the type within the .c file, it will only be visible within that .c file. The only way to make the type visible to multiple .c files is to declare it in a header and #include that header in each file that needs it.
Why is not possible to have static, predefined value for all vars of type struct s_t in c?
Because C struct types are simply not that sophisticated - they're just a way to define a data item with multiple attributes. The language doesn't provide any way to have members that are common across all instances of the type.
Remember that C is a product of the early 1970s and was originally developed to implement the Unix operating system - it was designed to be small, portable, and fast. A lot's been added to it over the last 40-some-odd years, but nothing that really changes the core philosophy of the language.
Well, its quite evident that you will get the warning. The reason is simple! You are trying to assign a Storage Class to the struct definition.
However, storage classes are applicable to variable declarations. Therefore, you are getting the prompt.
If you still wish to employ the static storage class, then you can do so with any variable, preferably, any instance of the structure.

Struct Scope Access

Hi this a continuation of a previous question I asked however I wasn't registered then and thus cannot edit the question. Anyways I have a struct
typedef struct
{
char input[100][100];
int count;
char name;
int startTime;
}INPUT;
extern INPUT *global;
this is within the header file. A stackoverflow member suggested that in my source file i use
INPUT global_[N], *global = global_;
to declare and initialise it which worked fine(as in I was able to store and print information out of the struct from within that method) however when I go to use the variable in other parts of my code it seems that the variable is out of scope?
I declare and use the variable global_ in a method called readFile and i'm trying to access the same information in main via *global.
Can this be done?
Thanks
Chee
extern INPUT *global;
This declares a global variable named global.
INPUT global_[N], *global = global_;
This defines an array global_ and a variable global. Depending on where this definition occurs (at function scope, or in a namespace, a class, or a function), global might or might not define the same object that's referred to by the declaration of global.

What does "static" mean in C?` [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicates:
What does “static” mean in a C program?
Static vs global
What does "static" mean in C, giving the following example: "static struct ........"?
And what is the diffrence between this and "struct ......" without the "static"?
Outside a function, static makes whatever it's applied to have file scope. For example:
int a_function(int x) { ... }
This function will have global linkage, and can be accessed by any other object file. You just have to declare it to use it, as is usually done in a header file:
int a_function(int x);
However, if you use static in the definition, then the function is visible only to the source file where it is defined:
static int a_function(int x) { ... }
In that case, other object files can't access this function. The same applies to variables:
static int x;
This makes x a global variable, visible only within it's source file. A "static struct" by itself doesn't do anything, but consider this syntax:
struct {
int x;
int y;
} p1, p2;
This declares two global variables (p1 and p2), each of an "anonymous" struct type. If you append static:
static struct {
int x;
int y;
} p1, p2;
Then static applies to p1 and p2, making them visible only within their source file.
static tells that a function or data element is only known within the scope of the
current compile.
In addition, if you use the static keyword with a variable that is local to a function, it allows the last value of the variable to be preserved between successive calls to that function.
So if you say:
static struct ...
in a source file no other source files could use the struct type. Not even with an extern declaration. But if you say:
struct ...
then other source files could access it via an extern declaration.
I'm not a C programmer, but if static in C means anything like it does in other languages I use STATIC STRUC, meaning that the structure is common amongst all instances of this class.
Say I had a class variable called Z. The usual behaviour is that the value of this variable is specific to a particular instance of a classs, but when it is static, all instances of the class share the same value of Z at all times.
I don't know how this applies to C, isn't C object-less?

C variables scope in struct

I've faced three separate situations in C lately that I would assistance on:
My C code has a global variable:
int ref_buf; //declared in a header file
In a function definition I use the same name as a parameter:
void fun(int ref_buf, param2, param3)
{
}
Will it overwrite the originally defined global variable and will it cause bugs?
Can I declare a static variable in a C data structure like so?:
struct my
{
int a;
static int b;
};
Does it work? Is there any specific situation where one would need it?
Can I initialize a individual structure variable as follows:
struct my
{
int a;
int b = 4;
};
Question 1
All references to ref_buf in that function will bind to the parameter and not the global variable.
Question 2
This is not legal in C but is legal in C++. The keyword static in C can only be used on file scope variables or on locals.
Question 3
No this is not legal in C (or C++). You will need to create a factory method to handle this.
my create_my() {
my m;
m.b = 4;
return m;
}
On Q3: GCC allows you to initialize a struct like this (as required by the C99 standard):
struct
{
int a;
int b;
} my = { .b = 4 };
GCC doc on designated initializers
1a) The local and global variables are separate entities, and so the local one won't overwrite the global. However, the global one won't be accessible inside the function (see also notes below).
1b) It not actually incorrect, but it is guaranteed to cause confusion, and confusion causes bugs, so it's best to use different names for each.
2) No, that's not legal C. You can however make the whole struct static.
3) No. You do it like this:
struct my
{
int a;
int b;
} = {0, 4};
Note 1: Variables should be declared in .c files, not .h files. If you need to make a variable accessible in multiple files, put an extern declaration in the header file.
Note 2: Avoid global variables if at all possible.
Question 1:
I think the variable declared in the local scope takes precidence, it shouldn't overwrite it but in the scope that the variable is declared it will be used instead.
That is assuming that it compiles.
On Q1:
Do not declare variables in a header file. If you include that header file in two source files and compile the source files together, you've got problems. Maybe your linker will get you out of them, maybe not.
If you really need global variables, and this happens a lot less than typical beginners think, put something like extern int ref_buf; in the header file, and int ref_buf; in a source file. That means there is one ref_buf, and all other source files will be able to find it.
The function parameter is essentially a new variable with the same name, and all references in the function will be to it. You will not be able to access the global variable from within that function. The function creates an inner scope, and variables declared in an inner scope are different from those in an outer one. This is potentially confusing, and makes it easy to create bugs, so having variables of the same name and different scopes is generally discouraged. (Variables of the same name in different struct definitions are usually not confusing, since you have to specify what struct contains the variable.)
The compiler will compile the function, but a good compiler will issue a warning message. If it refuses to compile because of one variable shadowing another of the same name, it isn't a real C compiler.
1) Local variables always take precedence e.g.
int ref = 10;
void fun(int ref)
{
printf("\n%d\n", ref);
}
int main()
{
fun(252);
return 0;
}
shows: 252
Qs 2 and 3 won't work in C.
Yes, it will technically overwrite, but a good compiler will warn you about this situation, and you will have "warnings = errors" on when you compile, so this won't actually compile.
Not needed, since the "my" struct is already declared as static, and it is therefore declared for the entire struct. This allocates the memory for the entire struct, so there is no need to say "take part of the struct which is already static and make it static".
No, not in the definition, but you can when you create an "instance", something like:
struct my MY =
{
{0, 4}
};

Resources