I am writing a data mashing function where I'm modifying audio data over time for a sort of dynamic bit-crusher audio filter. It is convenient for me to use static variables because their values carry over between function calls and this helps me achieve some interesting time-based effects by incrementing and so forth across rendering callbacks.
For example, one effect uses a sin function to modulate some sound effect over time. Like so:
void mangle(float * data, int n) {
static bool direction = false;
static float bottom = 0;
static float top = n;
static float theta = 0;
theta += 5;
// data = sin(theta) etc..
So I wish theta to be initialized once and than modified over time. Likewise, top wants to be static variable because I modify it later in the function also. In addition, top should take on the value of parameter n because n changes based on program state. But when I go to assign n to top, I get the compiler error
Initializer element is not a compile-time constsant.
Is there a way to assign a parameter to a static variable? Is there another way to accomplish what I want without static variables? I am aware I could use instance variables but I find that to be too much.
static variables are initialized before the program execution begins, so you cannot use a variable value to initialize a static variable. You'll need a compile-time constant value to initialize the static variable.
Quoting C11 standard, chapter §6.2.4, Storage durations of objects (emphasis mine)
[..] or with the storage-class
specifier static, has static storage duration. Its lifetime is the entire execution of the
program and its stored value is initialized only once, prior to program startup.
However, you can always assign a new value to the static variable.
That said, coming to the initialization part, as per chapter §6.7.9,
If an object that has static or thread storage duration is not initialized
explicitly, then
- ...
- if it has arithmetic type, it is initialized to (positive or unsigned) zero
- ...
so, you need not initialize the static floats explicitly to 0. You can assign any value, whatsoever later in the code.
In your case, top is a local static variable.
It is like global static variable and global variable that they all have static storage duration and they have value before the code startup.
The reason you have error similar to this case:
int a;
int b = a; \\initializer is not a constant
int main() {
...
}
With your purpose, use top as a global variable is a right way to go.
What you should do is create a struct that holds the data that is needed across calls and pass a pointer to the struct to the function. If you wnat to get fancy, you can create functions that allocate, initialize and free such a struct (and the user of the functions never needs to know what the contents of the struct are.
Something like:
struct mangle_t {
bool direction;
float bottom;
float top;
float theta;
};
struct mangle_t* mangle_open(void)
{
struct mangle_t* m = malloc(sizeof *m);
if (m) {
memset(m, 0, sizeof *m);
}
return m;
}
void mangle_close(struct mangle_t* m)
{
free(m);
}
void mangle(struct mangle_t* m, float * data, int n) {
m->top = n;
m->theta += 5;
}
As far as assigning a parameter to a static variable, you can just perofrm the assignment like any other variable (however, not as an initialization in the variable's declaration - that only happens once).
I'm not sure if you want to initialize top once and then keep it, but if so, this is what I would do:
void mangle(float *data, int n) {
static float top = -1; // Assuming that n will never be -1
if (top == -1)
top = n;
// .....
}
If you don't need to keep the value of top over function calls, there is no need to declare it static.
Related
What does the code below print when running the function print_test()?
struct test {
int a, b, c;
};
void print_test(void) {
struct test t = {1};
printf("%d/%d/%d", t.a, t.b, t.c);
}
Solution 1\0\0
Why are b and c initialized to zero even though I did not do it? Are there any default values for the struct?
However, the struct is not global and the member is not static. Why are they automatically zero-initialized? And if the data type were not int another data type to which value will be initialized?
If you don't specify enough initializers for all members of a struct, you'll face Zero initialization, which will initialize remaining members to 0. I think by today's standards this seems a bit odd, especially because C++'s initialization syntax has evolved and matured a lot over the years. But this behavior remains for backwards-compatibility.
I think we need to know two points at this stage:
There is nothing different between regular variables and structs, if they are at local scope i.e automatic storage duration. They will contain garbage values. Using those values could invoke undefined behaviour.
The only thing that makes structs different is that if you initialise at least one of the members, the rest of the members will get set to zero i.e. initialised as if they had static storage duration. But that's not the case when none of the members are initialised.
It depends on your declaration.
If your declaration is outside any function or with the static keyword (more precisely, has static storage duration), the initial value of x is a null pointer (which may be written either as 0 or as NULL).
If it's inside a function i.e. it has automatic storage duration, its initial value is random (garbage).
consider the following code:
#include<stdio.h>
#include<unistd.h>
struct point {
int x, y;
char a;
double d;
};
typedef struct point Point;
void main(){
Point p1;
printf("\nP1.x: %d\n", p1.x);
printf("\nP1.y: %d\n", p1.y);
printf("\nP1.a: %d\n", p1.a);
printf("\nP1.d: %lf\n", p1.d);
Point p2 = {1};
printf("\nP2.x: %d\n", p2.x);
printf("\nP2.y: %d\n", p2.y);
printf("\nP2.a: %d\n", p2.a);
printf("\nP2.d: %lf\n", p2.d);
}
The output is :
P1.x: 0
P1.y: 66900
P1.a: 140
P1.d: 0.000000
P2.x: 1
P2.y: 0
P2.a: 0
P2.d: 0.000000
A Good read: C and C++ : Partial initialization of automatic structure
I have recently run into some trouble while trying to perform the following logic:
static const int size = getSize();
int getSize() {
return 50;
}
The error I have received is initialiser element is not constant
Having read online I understand that this issue is because the compiler evaluates the static const expression at compilation and therefore cannot know what the value is supposed to be.
My question is how do I get around this?
If I have a library that contains many functions but they all require this logic how are they supposed to use it without having to calculate it each time?
And even if they have to, what if the logic itself can change throughout runtime but I only ever want the first value I receive from the function?
Perhaps I should clarify that the logic in getSize is just an example, it could also contain logic that retrieves the file size from a specific file.
Unlike in C++ you cannot initialize global variables with the result of a function in C, but only with real constants known at compile time.
You need to write:
static const int size = 50;
If the constant must be computed by a function you can do this:
Dont declare static const int size = ... anymore, but write this:
int getSize()
{
static int initialized;
static int size;
if (!initialized)
{
size = SomeComplexFunctionOfYours();
initialized = 1;
}
return size;
}
int main(void)
{
...
int somevar = getSize();
...
That way SomeComplexFunctionOfYours() will be called only once upon the first invocation of getSize(). There is a small price to be paid: each time you invoke getSize(), a test needs to be performed.
Or you can initialize it explicitely like this, but then size cannot be const anymore:
static int size;
void InitializeConstants()
{
size = SomeComplexFunctionOfYours();
}
int main(void)
{
InitializeConstants();
...
int somevar = size;
...
The compiler needs to know the value of your constant variable at the compilation time, because its a constant.
Also you can't initialize a variable with a function.
You should do something like this :
#define SIZE 50
static const int size = SIZE;
I have the following structure:
typedef struct
{
uint8* buffer;
uint32 bufferLength;
} SRequest;
and a function:
void somefunction(const SRequest* request)
{
//The following initialization of the pointer to static structure is not working
static SRequest* request_ptr = {.buffer = request->buffer,
.bufferLength = 0};
.
.
}
Is there another way I can initialize the request_ptr?
You are trying to initialize a pointer with a value that is not a pointer but rather a struct. That cannot possibly work.
Moreover, initializers for objects with static storage duration must be compile-time constants. This constraint makes sense when you recognize that initialization of such objects happens (logically) before program execution starts. All file-scope variables have static duration, as do local variables declared static, such as your request_ptr. You are trying to initialize your static pointer with a value that is not a compile-time constant.
It is unclear what you are really after, here, but if you are trying to create, on each call, an SRequest that points to the same buffer that the argument does, then that could be this:
void somefunction(const SRequest* request)
{
SRequest local_request = {.buffer = request->buffer,
.bufferLength = 0};
.
.
.
}
Note there that I make local_request an automatic variable rather than a static one, so that its initializer is applied on every call, and that I make it a struct, not a pointer to one.
On the other hand, if your objective is to have an SRequest that is initialized on the first call to the function with values derived from the argument to that call, and thereafter persists across function calls, then you want something like this:
void somefunction(const SRequest* request)
{
static int initialized = 0;
static SRequest local_request;
if (!initialized) {
local_request.buffer = request->buffer;
local_request.buffer_length = 0;
initialized = 1;
}
.
.
.
}
You might be able to do without the initialized variable if a member of local_request would be suitable in its stead. For instance, perhaps it would work for your purposes to instead test weather local_request.buffer is NULL.
In any event, it's unclear to me why you would want the local variable to designate a pointer instead of a structure. There are potential reasons why you might indeed want that, but it's not evident that any of those apply.
As the title of the question seems more explicit than the cited one by terence hill, it might be interesting to have the answer here.
You have to use "compound literal", which is defined in the C99 standard:
void somefunction(const SRequest* request)
{
//The following initialization of the pointer to static structure is not working
static SRequest* request_ptr = &(SRequest){
.buffer = request->buffer,
.bufferLength = 0};
}
I would like to return a function with a variable inside it that I can initialize inside the function that returns it. Possible, or no?
int get_char (char *c)
{
static circular_queue *cir; // this needs to be initialized in the function below
if (circular_queue_empty(cir))
return 0;
else
*c = circular_queue_pop(cir);
return 1;
}
int (*generate_get_char(circular_queue *cir)) (char *c)
{
// do something to set cir
return &get_char;
}
I am passing the pointer to getchar into an API that I do not control so I cannot change the format of get_char; that being said, is there a better way of doing this as I am pretty sure the above is not possible. (I would rather not use a static global, but thats all I can think of doing).
TY
Variables which have static storage allocation are default initialized to zero. Therefore, the following statements are effectively equivalent.
static circular_queue *cir;
// equivalent to
static circular_queue *cir = 0;
// equivalent to
static circular_queue *cir = NULL;
The variable cir has function scope, i.e., it can be accessed only in the function get_char. Therefore, the answer to your question
I would like to return a function with a variable inside it that I can
initialize inside the function that returns it. Possible, or no?
is no. You need a global variable which is visible to both the functions get_char and generate_get_char. Also, note that a function name implicitly converts to a pointer. Therefore, the following are equivalent -
return &get_char;
// equivalent to
return get_char;
This is not possible - cir is accessible only from get_char and there is no way to access it from outside. You need a static global visible by both functions.
I am doing research on static and const keywords.
Static: Use the static modifier to declare a static member, which belongs to the type itself rather than to a specific object.
const: You use the const keyword to declare a constant field or a constant local. This keyword specifies that the value of the field or the local variable is constant, which means that it can't be modified.
I would like to know about example when programmers would use static and const keywords.
const variables, or constant, would be used to declare a value that won't change or you want to prevent from being changed. For example, Pi could be declared as a constant in C++.
const double kPi = 3.14159265359;
static variables are a bit different. There is only one instance of the static variable that persists across classes\functions.
For example:
void foo()
{
static int bar = 0;
printf("%d\n", bar);
++bar;
}
int main()
{
int i;
for(i = 0; i < 5; ++i)
{
foo();
}
}
Would print:
0
1
2
3
4
Even though bar goes out of scope, its value is still in memory, so its only initialized once. Each time the foo() is called, that value gets incremented.
Edit:
To clarify, the compiler will actually reserve memory for the static variable within the assembly code that it produces. Additionally, the static keyword also tells the compiler to initialize the variable exactly once. The scope of the variable is the same (inside the foo function), but it is only initialized once in the above case. Automatic variables (such as int i) are pushed onto the call stack when the function is called.
(All of this is for Langage C++)
Hi, you can use const and static keywords in few cases, for exemple :
Const
First, used to say that the variable cannot be modified.
int main()
{
const int toto[4] = {0, 1, 2, 3};
return (0);
}
// We cannot modify toto after it declaration, why is it usefull? It keeps the state of your program design
Second, used to say that a method do not modify the object state.
class toto
{
int i;
public:
int geti() const;
}
// All getter in CPP use it. Why is it usefull? Developper who use the class know that he do not modify the object state
Third, used to say that the parameter pass to a function isn't modify by the function.
int function(const std::string &str)
{
// function cannot modify the object string pass in parameter
}
Static
First, used to say that a implemented function is know only inner a single file.
static int fct()
{
return (0);
}
// You can ony call function fct() if you are inner the file who it is implemented
Second, used to say that a argument or method is common to all object of the same class.
class toto
{
public :
static int getLol();
};
// Every object totoObj1, totoObj2 ... will call same function
Third and the last one, used to say that a variable do not change state between multiple call of the same function where it is declared
void fct()
{
static i = 0;
std::cout << ++i << std::endl;
}
// This function are going to print 1 then 2 then 3 ...
If you have any questions, you are welcome :)
If you want to have any variable/method to be available irrespective of an object you go for a static member but if you want the same to be unmodifiable as well then const is the solution. Following example can help you understand this.
In below example
PI is defined as a constant and can not/should not be changed
ONLINE holds number of users online, it can change but should be available irrespective of objects
public class Example
{
//PI should not be changed, with reasons known that it is a constant
public const double PI = 3.14;
//Users currently using the application
public static int ONLINE = 0;
public Example(){ ONLINE++; }
public void dispose(){ ONLINE--; }
public static int loggedInUsers(){ return ONLINE; }
public void GetArea(int radius){return PI*radius*radius; }
}