How can I do global constant initialization like this? Is it possible at all? Or there is another way to do what I want? I mean I need global parameters gained from main() and they must be constants.
#include <stdio.h>
#include <stdlib.h>
const int var;
int main(int argc, char *argv[]) {
var = atoi(argv[1]);
/* ... */
return 0;
}
I need global parameters gained from main() and they must be constants.
No portable way to do directly as OP wants.
Code needs different access for reading and writing. Effectively hiding the access to the true data.
A close solution it to set and get data via functions defined in another file. Then no way to change data once set and only settable once.
main_var.h
int main_var_get(void);
void main_var_set(int v);
main_var.c
#include <stdlib.h>
#include "main_var.h"
static int var; // This could instead be a struct of many members.
// Or a pointer to a struct with many members.
static int var_init;
int main_var_get(void) {
if (!var_init) {
// Handle call of get before set, perhaps exit or return default value
exit(EXIT_FAILURE);
}
return var;
}
void main_var_set(int v) {
if (var_init) {
// Handle 2nd set, perhaps exit or ignore
exit(EXIT_FAILURE);
}
var = v;
var_init = 1;
}
main.c
#include <stdio.h>
#include "main_var.h"
int main(void) {
main_var_set(42);
...
printf("%d\n", main_var_get());
}
Another is to use a const int *. Access before setting is the same no-no as dereferencing NULL. Attempting to write *main_var_addr is UB like writing any const object.
main_var.h
extern const int *main_var_addr;
void main_var_set(int v);
main_var.c
#include <stdlib.h>
#include "main_var.h"
const int *main_var_addr = NULL;
static int var;
void main_var_set(int v) {
if (main_var_addr) {
// Handle 2nd set attempt, perhaps exit or ignore
exit(EXIT_FAILURE);
}
var = v;
main_var_addr = &var
}
main.c
#include <stdio.h>
#include "main_var.h"
int main(void) {
main_var_set(42);
...
printf("%d\n", *main_var_addr);
}
I don't think C allows you to initialize a constant variable elsewhere. However, you can just change var from const to static.
This is not possible, actually const doesn't mean the variable is constant in C, it's only mean that you are not allowed to change the value of the variable, but someone else could.
Global value are initialize before the main run, that mean you can't initialize at runtime, how this initialization is done is implementation behavior so there is no "pure C" way to do what you ask.
However, I don't see why you could not encapsulate your global:
my_var.h:
int init_my_var(int argc, char **argv);
int get_my_var(void);
my_var.c
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
static int var;
int init_my_var(int argc, char **argv) {
#ifndef NDEBUG
#include <stdbool.h>
#include <assert.h>
{
static bool first = true;
assert(first);
first = false;
}
#endif
if (argc < 2) {
return 1;
}
errno = 0;
long ret = strtol(argv[1], NULL, 10);
if (errno || (ret < INT_MIN || ret > INT_MAX)) {
return 2;
}
var = (int)ret;
return 0;
}
int get_my_var(void) {
return var;
}
main.c:
#include <stdio.h>
int main(void) {
printf("%d\n", get_my_var());
if (init_my_var(2, (char *[]){"", "42"})) {
return EXIT_FAILURE;
}
printf("%d\n", get_my_var());
if (init_my_var(2, (char *[]){"", "0"})) {
return EXIT_FAILURE;
}
}
Related
I need to know a way for use environment variables in the C programming language. How can I use and read them?
For example, read an environment variable or take the value of an environment variable and load it in another variable.
You can use following functions -
char * getenv (const char *name)-returns a string that is the value of the environment variable name.
char * secure_getenv (const char *name)
Read about some more functions here -http://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access
Use the getenv function from stdlib.h. That's it!
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("test\n");
const char* s = getenv("PATH");
// If the environment variable doesn't exist, it returns NULL
printf("PATH :%s\n", (s != NULL) ? s : "getenv returned NULL");
printf("end test\n");
}
getenv:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char* my_env_var = getenv("MY_ENV_VAR");
if(my_env_var)
printf("Var found: %s", my_env_var );
else
printf("Var not found.");
return 0;
}
On windows, you would use GetEnvironmentVariable.
#include <stdio.h>
#include <winbase.h>
int main(int argc, char *argv[])
{
TCHAR buff[100] = T("");
DWORD resultLengthInCharacters = GetEnvironmentVariable(T("USERDOMAIN"), buff, 100);
if (resultLengthInCharacters > 0 && resultLengthInCharacters < 100) {
_tprintf(T("USERDOMAIN: %s\n"), buff);
} else if ( resultLengthInCharacters > 100) {
_tprintf(T("USERDOMAIN too long to store in buffer of length 100, try again with buffer length %lu\n"), resultLengthInCharacters);
} else {
// Error handling incomplete, should use GetLastError(),
// but typically:
_tprintf(T("USERDOMAIN is empty or not set in the Environment\n"));
}
return 0;
}
But if you are trying to get a standard path variable, you should use the SHGetFolderPath function with the right CSIDL variable (like from this question: How do I get the application data path in Windows using C++?)
Another way could be to use the global variable environ.
#include <stdio.h>
extern char** environ;
void main(int argc, char* argv[])
{
int i=0;
while(environ[i]!=NULL){
printf("%s\n",environ[i++]);
}
}
I wanted to create a simple program to better understand how the pointers work and I came across a problem. I want to work on 3 files main.c modul.c and modul.h.
modul.h
typedef struct
{
int data;
}w_options;
int show(); //prototype of function
modul.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "modul.h"
int show()
{
w_options *color;
color = (w_options *)malloc(sizeof(w_options));
printf("%d\n", color->data);
if (color->data == 1)
{
printf("Good\n");
}
else
{
printf("Bad\n");
}
}
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "modul.h"
int main()
{
w_options *color;
color = (w_options *)malloc(sizeof(w_options));
color->data=1;
printf("%d\n", color->data);
show();
}
In main.c I am setting the value of color->data to 1 and it's working, it's printing 1. But I would like to pass this set value to modul.c. That's way I created simple if instruction to check if the value is passed. Unfortunately the value isn't passed and I don't have idea how to fix it. I need this kind of solution for my bigger program.
The Output:
1
0
Bad
You just have to pass it as an argument to your function. And, as your function returns nothing, declare it as void.
modul.h
typedef struct
{
int data;
}w_options;
void show(w_options *color); //prototype of function
modul.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "modul.h"
void show(w_options *color)
{
if (color->data == 1)
{
printf("Good\n");
}
else
{
printf("Bad\n");
}
}
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "modul.h"
int main()
{
w_options *color;
color = (w_options *)malloc(sizeof(w_options));
color->data=1;
printf("%d\n", color->data);
show(color);
return EXIT_SUCCESS;
}
Currently you aren't passing any values.
In modul.c you're creating one pointer named color that has no initialized values, you are only allocating memory.
color = (w_options *)malloc(sizeof(w_options));
printf("%d\n", color->data);
It's an accident that it happens to print 0 as the current value. This isn't guaranteed at all.
In main.c you're creating another different pointer, also named color but in a different scope, whose own color->data is set to 1.
color = (w_options *)malloc(sizeof(w_options));
color->data=1;
printf("%d\n", color->data);
This correctly prints 1 as the current value because you've initialized it properly.
If you want show to use a pointer, pass the pointer to it as an argument and use it on the other end.
main.c
...
show(color);
...
modul.c
...
int show(w_options *color)
{
// this is a parameter now, receiving the value from its caller
//w_options *color;
//color = (w_options *)malloc(sizeof(w_options));
printf("%d\n", color->data);
if (color->data == 1)
{
printf("Good\n");
}
else
{
printf("Bad\n");
}
}
...
I type this code to get the home directory. I have later edited it to include all of the code:
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdarg.h>
#include "anotherfile.h"
typedef unsigned int uint;
void Interval(void) {
static uint S = 0;
static uint C = 0;
static uint M = 0;
static uint D = 0;
usleep(10e5/0x20);
printf("%d\n", C);
printf("%d\n", S);
printf("%d\n", M);
if(C == 0x20) {
if(S == 59) {
S=0;
M++;
}else{S++;}
C=0;
}else{C++;}
Interval();
}
int main(int argc, const char *argv[]) {
char *HomeDir;
if((HomeDir = getenv("HOME")) == NULL) {
HomeDir = getpwuid(getuid())->pw_dir;
if(HomeDir == NULL) {
printf("Failed to get Home Directory\n");
}else{printf("Retry Home Directory Found\n");}
}else{printf("Success getting Home Directory\n");}
Interval();
return 0;
}
It gives me the implicit declaration warning. It says something is wong with the getenv partHow can I fix it?
The function getenv is declared in stdlib.h according to this reference. So you need to add
#include <stdlib.h>
i want to assign value of an integer array to integer pointer. The pointer takes a different value of assignment. Please help me on this.
I have assigned 2 for port_val variable. But, after assigning that to ofport_request var, the value becomes different.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
int main ()
{
printf("INSIDE MAIN..\n");
int64_t of_port[100];
int count=2;
int i;
int port_val = 2;
int port_next_val = 4;
size_t n_ofport_request = 1;
int64_t *ofport_request = malloc(sizeof *ofport_request * (n_ofport_request));
for(i=0;i<count;i++) {
if(i == 0) {
of_port[i] = port_val;
} else {
of_port[i] = port_next_val;
}
ofport_request[0] = of_port[i];
printf("OFPORT VAL = %d\n",ofport_request);
}
return 0;
}
If you want to print the pointer variable, you have to use the * before the variable name.
Use the below printf statement it will work.
printf("OFPORT VAL = %lld\n",*ofport_request);
I need several global pointers to be shared among a few files - the pointers are essentially arrays of double whose lengths are only determined at runtime.
I include here the pieces of the code that caused the issue. This is not the exact code, but it illustrates all the points precisely:
foo.h
#ifndef FOOH
#define FOOH
/* ------------------
COMMON VARIABLES
---------------------*/
// create_bundles.c
extern double *all_bundle;
/* ------------------
COMMON FUNCTIONS
---------------------*/
// create_bundles.c
void create_bundles(int num_firm);
// memory_allocation.c
void allocate_memory(int num_firm, int num_bundle);
void clean_memory(void);
#endif
create_bundles.c
#include "foo.h"
extern double *all_bundle;
void create_bundles(int num_firm) {
int i;
for (i = 0; i < num_firm; i++) {
all_bundle[i] = 1
}
memory_allocation.c
#include "foo.h"
// create_bundles.c
double *all_bundle = NULL;
void allocate_memory(int num_firm, int num_bundle) {
all_bundle = calloc(num_bundle * num_firm, sizeof(double));
}
void clean_memory(void) {
free(all_bundle);
}
main.c
#include "foo.h"
void main(int num_firm, int num_bundle) {
allocate_memory(num_firm, num_bundle);
create_bundles(num_firm);
clean_memory();
}
What happened is that if I print out all_bundle[i] it'll all be 0, and then it'll give me a segmentation error.
Why the error and how to fix it?
The problem is not in global pointer, but something else. Keep looking for the problem in your common code. I hope you are trying to print contents of all_bundle array before calling clean_memory. I have edited your code a little bit and it works great without any segmentation errors and prints 1.0000. Here it is, take a look:
foo.h:
#ifndef FOOH
#define FOOH
// create_bundles.c
extern double *all_bundle;
// create_bundles.c
void create_bundles(int num_firm);
// memory_allocation.c
void allocate_memory(int num_firm, int num_bundle);
void clean_memory(void);
#endif
memory_allocation.c:
#include <stdlib.h>
#include "foo.h"
double *all_bundle = 0;
void allocate_memory(int num_firm, int num_bundle) {
all_bundle = calloc(num_bundle * num_firm, sizeof(double));
}
void clean_memory(void) {
free(all_bundle);
}
create_bundles.c:
#include "foo.h"
void create_bundles(int num_firm) {
int i;
for (i = 0; i < num_firm; i++) {
all_bundle[i] = 1;
}
}
main.c:
#include <stdio.h>
#include "foo.h"
int main(int argc, char *argv[]) {
allocate_memory(100, 1);
create_bundles(100);
{
int i;
for(i = 0; i < 100; ++i)
printf("%f\n", all_bundle[i]);
}
clean_memory();
return 0;
}
Have a header file to access the memory (i.e. add stuff to it, remove stuff from it, readf bits of it, etc).
Have the corresponding .c (or .cpp if that fancies you) to do the magic. And then use static to define the memory.
This is a simple and easy solution to your problem and also enables you to change the implementation if it is required to do so.