Define array in header and storing it in stack - c

I need to define a global array which has to be visible in every file. I declared it in a header file, but it's stored in heap e not in stack. How can i put it in stack? Thank you
EDIT:
I'm using an ATMEGA32 and array is put at the begin of the RAM (address 0x0060), while I need to put it at the end (address 0x085F)
common.h
#define dimension 5
unsigned int board[dimension][dimension];
main.c
#include "common.h"

You have a definition of the array variable in the header file. If you include it in more than one file you will have duplicate (or multiple) definitions of the same global variable which will be reported as an error by the linker.
In the header file you should have a declaration only like
extern unsigned int board[dimension][dimension];
and a definition in exactly one C file at file scope, i.e. not in a function. For example you can use this definition in main.c
unsigned int board[dimension][dimension];
It must be this way if you want to access the variable from more than one .c file.
To put this variable on the stack it must be inside a function, e.g. in main(), but this way you cannot use it as a global variable. You could use a pointer variable as a global variable and initialize this in main() with the address of the array. This has the drawback that the functions that use the pointer cannot determine the two array dimensions from the variable itself. Of course they could use the preprocessor symbol.
Example:
common.h
#ifndef COMMON_H
#define COMMON_H
#define dimension 5
extern unsigned int (*board)[dimension];
#endif // COMMON_H
main.c
#include "common.h"
#include "other.h"
unsigned int (*board)[dimension];
int main(void)
{
unsigned int the_board[dimension][dimension] = {{ 0 }};
board = the_board;
printf("board[1][2] = %d\n", board[1][2]);
some_function();
printf("board[1][2] = %d\n", board[1][2]);
return 0;
}
other.h
#ifndef OTHER_H
#define OTHER_H
void some_function(void);
#endif // OTHER_H
other.c
#include "common.h"
#include "other.h"
void some_function(void)
{
board[1][2] = 3;
}
If you want to have the variable at a specific address or in a specific address range (but not on the stack) you could use a (linker specific) linker script to define a memory section at a specific address range and use a (compiler specific) #pragma section("name") or __attribute__((section("name"))) to put a normal global variable into this memory section.

Related

Array implementation of stack data structure

I am trying to implement an array implementation of a stack. I am new to stack and I have tried to implement the push operation in c, and here is my code:
#include "stack.h"
/**
* push_arr_stack - pushes an element to the stack
* #n: The number that will be pushed to the stack
*
* Return: It returns nothing
*
*/
void push_arr_stack(int n)
{
top = top + 1;
stack_arr[top] = n;
}
Here is my header file:
#ifndef STACK_H
#define STACK_H
#define MAX 4
extern int stack_arr[MAX];
extern int top = -1;
void push_arr_stack(int n);
#endif
And I have tried the push operation using the following test function:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
/**
* main - Entry point for my program
*
* Return: On success, it returns 0,
* On error, it returns -1
*/
int main(void)
{
push_arr_stack(7);
return (0);
}
But I get the following error,
gcc -Wall -Werror -Wextra -pedantic -std=gnu89 main.c 0-push_arr_stack.c
In file included from main.c:4:
stack.h:6:12: error: ‘top’ initialized and declared ‘extern’ [-Werror]
6 | extern int top = -1;
| ^~~
cc1: all warnings being treated as errors
In file included from 0-push_arr_stack.c:1:
stack.h:6:12: error: ‘top’ initialized and declared ‘extern’ [-Werror]
6 | extern int top = -1;
| ^~~
cc1: all warnings being treated as errors
I need the top variable to track which index is the top of the stack, but it is giving me the error that top is initialized and declared. How can I make it so I can initialize top to -1
Either those variables should be local to stack.c or to the caller. They should not be declared at file scope (outside any function). By declaring something extern, you state that "this is allocated elsewhere". But you never actually allocate it elsewhere, hence the problems. Also, since it is allocated elsewhere, the initialization has to be placed elsewhere too.
However, using extern like this is very bad practice, since it creates global variables and spaghetti code, where one variable is shared across multiple files even though it shouldn't.
Instead you could place all those variables inside a struct. For beginner-level applications it is probably sufficient to just do like this:
// stack.h
typedef struct
{
int stack_arr[MAX];
int top;
} stack;
void stack_init (stack* s);
And then:
// stack.c
void stack_init (stack* s)
{
/* default initialization here */
s->top = -1;
}
Now the caller of your code can include stack.h, declare a variable stack my_stack; and then call your functions like stack_init(&my_stack);.
For professional applications, the above may not be considered good enough, since it violates the best design practice known as private encapsulation. The caller gets access to internal variables of the struct even though they shouldn't. In such cases one could implement opaque types to fix this: How to do private encapsulation in C?
The header file is included in two translation units: with main and with the function definition. So the variable top is defined twice.
In the header file just declare the variable
extern int top;
and in main define it like
int top = -1;
before the function main after the header.
Pay attention to that a variable declared in a file scope with the storage class specifier extern and with an initializer represents a definition of the variable. You may not define a variable with external linkage twice.
From the C Standard (6.9.2 External object definitions)
1 If the declaration of an identifier for an object has file scope and
an initializer, the declaration is an external definition for the
identifier.
Pay attention to that in general it is not a good approach to use global variables.

Confusion about the extern keyword and multiple source files

I am trying to fully understand how extern works, so I created 3 files, two of them are source files and the last is a header file. This is what is contained in each of them:
testingfile1.c
#include <stdio.h>
#include "testingheader.h"
int main() {
change();
int my_extern;
printf("\n%d", my_extern);
return 0;
}
testingfile2.c:
#include <stdio.h>
#include "testingheader.h"
void change() {
int my_extern;
my_extern = 15;
printf("%d", my_extern);
}
testingheader.h:
#if !defined(TESTINGHEADER_H)
#define TESTINGHEADER_H
#include <stdio.h>
extern int my_extern;
void change();
#endif
The output of this program is: 15 0. However, I thought that since my_extern is an extern int, if you were to change to the value in one source file, it's value would be changed in all of the other source files. Is this not how extern works, or am I doing something wrong in the code itself?
In both cases remove int my_extern; where you have it, because those become local variables which happen to have the same name my_extern.
extern int my_extern; just means there's an int called my_extern "out there somewhere". So you'd have to declare int my_extern somewhere at file scope, for example like this:
int my_extern = 0;
void change() {
my_extern = 15;
printf("%d", my_extern);
}
In testingfile2.c, the my_extern variable is local to the function and you are not seeing the global my_extern that the extern command is referencing. Of course, you don't have a global my_extern, so that is another problem. You would get a linker error if you actually tried to reference the global my_extern that the extern command is referencing.
The issue is you're re-declaring int my_extern; inside your functions. Therefore, C treats that as a separate variable from the global my_extern.
The statement extern int my_extern; is a declaration that a global int called my_extern will be declared somewhere. You haven't done that. Instead, you've created local my_extern variables.

In C language, Static Variable with pointer access

My question is about Memory and how it is being accessed across a program with multiple C files (Multiple Modules).
file1.h Version 1
#ifndef file1_h
#define file1_h
typedef struct
{
UINT8 var1;
UINT16 var2;
UINT16 var3;
} TestAccess;
static TestAccess* pLongRangeAccess;
#endif
file1.h Version 2
#ifndef file1_h
#define file1_h
typedef struct
{
UINT8 var1;
UINT16 var2;
UINT16 var3;
} TestAccess_t;
TestAccess_t* pLongRangeAccess;
#endif
Main.c
#include "file1.h"
void main(void)
{
pLongRangeAccess->var1 = 4;
pLongRangeAccess->var2 = 8;
pLongRangeAccess->var3 = 16;
}
Module1.c
//Needs read/write access to the struct variables
#include "file1.h"
void module1(void)
{
pLongRangeAccess->var1 = 5;
pLongRangeAccess->var2 = 10;
pLongRangeAccess->var3 = 20;
}
Question 1) See "Version1" Does static in keyword make it such that there will be only one copy in heap memory (uninitialized) and therefore only one address of the pointer variable OR would it create 2 static variables with different memory since the header is used in every module?
Question 2) see "Version 2" If static was not declared for the pointer variable, then it would still be in heap memory and there would be one UNIQUE address that could be used to accessed to read and write operations to the members?
Question 3) In version 2 of file1.h if the pointer was declared in Main.c, and the memory location was fixed i.e it was declared as a constant, would it be available for access from any module by de-referencing the memory address location?
I think you are mixing up "memory allocation" with variable declaration and variable definition. I think what you want is to share a variable pLongRangeAccess among different translation units, such that it exists only once in your program. To do that, declare the variable in the header file, and define it once in a single c-file:
#ifndef file1_h
#define file1_h
typedef struct
{
UINT8 var1;
UINT16 var2;
UINT16 var3;
} TestAccess;
extern TestAccess* pLongRangeAccess;
#endif
And then the .c-file:
// file1.c:
#include "file1.h"
TestAccess* pLongRangeAccess;
Note that keyword static, when applied to variables outside any function, means that this variable is private to the respective translation unit; this is mainly for information hiding and for avoiding unintended name clashes with other translation units (from different vendors, probably).
So, if you write
// file1.c
static TestAccess* pLongRangeAccess;
// file2.c
static TestAccess* pLongRangeAccess;
, then translation unit file1 and file2 both have their own private variable pLingRangeAccess, which is not visible to other translation units (regardless if any head file declares the variable as extern). The linker will not complain any "duplicate variable definition" in this case, as - as mentioned - the variables are private to their TU.
If you write, however, the following
// file1.c
TestAccess* pLongRangeAccess;
// file2.c
TestAccess* pLongRangeAccess;
, then both variables become visible to the other translation units, and the linker will complain that variable pLongRangeAccess is defined twice in your program, which is not allowed.

Using structs in multiple files

I am trying to call a function in main.c from io.h that reads data from a file, stores that data into multiple structs, then somehow lets me pass the different structs as arguments in later functions in main. Those later functions will be defined in other files, such as alg.h.
How do I go about doing this? Do I use extern and make the structs global and put them in a separate file? Is it possible to have a function from alg.h have a return type of one of the structs? Does it depend on the order of my includes?
The code pasted below complies and works, but any attempt to move either of the structs causes the program to not compile.
Also, is it possible to have, for example, a struct declared in alg.h, then functions that have that struct as a parameter declared later in alg.h. Then in main.c, you initialize and pass the struct into a function declared in io.h, give the struct some values, have it returned to main.c, then pass that into the function declared in alg.h? I know that sounds like a class, but I need a C solution and I only need one instance of the struct floating around.
Thanks.
io.h
struct s1 {
int num1;
double num2;
};
struct s2 {
int num3;
double num4;
};
void io_init(struct s1*, struct s2*);
io.c
#include <stdio.h>
#include <stdlib.h>
#include "io.h"
void io_init(struct s1* s1i, struct s2* s2i)
{
s1i->num1 = 5;
s1i->num2 = 2.4;
FILE *fp;
char line[80];
fp = fopen("input.txt","rt");
fgets(line, 80, fp);
sscanf(line,"%i",&s2i->num3);
fgets(line, 80, fp);
sscanf(line,"%i",&s2i->num4);
fclose(fp);
}
alg.h
void ga_init(struct s1);
alg.c
#include <stdio.h>
#include "io.h"
#include "ga.h"
void ga_init(struct s1 s1i)
{
printf("%i", s1i.val1);
}
main.c:
#include <stdio.h>
#include "io.h"
#include "ga.h"
int main() {
struct s1 s1i;
struct s2 s2i;
io_init(&s1i, &s2i);
ga_init(s1i);
return 0;
}
Every file which requires the declaration of your types (i.e., wants to use them) must include your header file (ok, so forward declarations and pointers will work, but they can't be dereferenced without the definition and that's not really applicable here anyway.)
So, to elaborate, if file X needs to use struct Y then it needs to include the header file which contains its declaration, that's it.
/* X.c */
#include "Y.h" /* <-- that's it! */
void foo(Y *obj) {
/* ... */
}
Here is some advice.
Your .h file is not defining struct objects. It's just defining the type. It's fine the way it is. Everyone who touches any struct of those types should include this file.
It's very rare to need to pass a struct by value as you are doing in the call to ga_init. You will essentially always want to call by reference, like you did with io_init.
Yes, you can return a struct, but again, it would almost always be better to return a reference to a struct.
You can certainly share globally defined structs and you don't need extern unless your linker is something awful. But sharing a reference to a struct allocated in main() amounts to roughly the same thing.

variable between files [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I share variables between different .c files?
If I have two source files, and one header: file1.c, file2.c, and header.h, and:
--header.h--
int i;
--file1.c--
#include <header.h>
i = 10;
int main() {
func();
return 0;
}
--file2.c--
#include <header.h>
void func() {
printf("i = %d\n", i);
return;
}
I get the warning that i defaults to an int. What could I do if I want to have i as a float for instance?
Make it
extern int i;
in the header and
int i = 10;
in file1.c.
The warning means that for the (incomplete) declaration i = 10; in file1.c, the "implicit int" rule is applied, in particular, that line is interpreted as a declaration (since an assignment cannot appear outside function scope).
You have a couple of errors in your code. The first is that you define the variable i in the header file, which means that it will be defined in all source files that include the header. Instead you should declare the variable as extern:
extern int i;
The other problem is that you can't just assign to variables in the global scope in file1.c. Instead it's there that you should define the variable:
int i = 10;
Declare it as extern in the header (this means memory for it is reserved somewhere else):
/* header.h */
extern int i;
Then define it in only one .c file, i.e. actually reserve memory for it:
/* file1.c */
int i = <initial value>;
In the header use
extern int i;
in either file1.c or file2.c have
int i = 20;
If you want float just change int to float
In 99.9% of all cases it is bad program design to share non-constant, global variables between files. There are very few cases when you actually need to do this: they are so rare that I cannot come up with any valid cases. Declarations of hardware registers perhaps.
In most of the cases, you should either use (possibly inlined) setter/getter functions ("public"), static variables at file scope ("private"), or incomplete type implementations ("private") instead.
In those few rare cases when you need to share a variable between files, do like this:
// file.h
extern int my_var;
// file.c
#include "file.h"
int my_var = something;
// main.c
#include "file.h"
use(my_var);
Never put any form of variable definition in a h-file.

Resources