How to initialize global pointer to extern variable? - c

Lets say I have the following struct:
typedef struct
{
uint8_t *ptr;
} Example;
If I have in file1.c:
// Global variable
uint8_t myVar;
How can I initialize an Example with the ptr member pointing to myVar, in file2.c?
I know I could just do:
extern uint8_t myVar;
// Global variable
Example myExample = {.ptr = &myVar};
But myVar would be visible in all the scope of file2.c and I'm trying to avoid that.

A pointer or other object can be made available within a source file without making symbols used in its initializers be visible by declaring it extern in one source file (or more) and defining it in a separate source file.
Create a separate C file, such as myExample.c, containing a definition of myExample:
#include "myExample.h"
extern uint8_t myVar;
Example myExample = { .ptr = &myVar };
Create a header file, such as myExample.h, that declares myExample:
typedef struct
{
uint8_t *ptr;
} Example;
extern Example myExample;
Then include the header file in any source file where you want to use myExample. That source file will see myExample but not myVar.
Also compile the new C file and link it in with your program.

you need to add the function in the file.c
static uint8_t myVar;
uint_8 *getMyVat(void)
{
return &myvar;
}
in file2.c
void foo(void)
{
Example myExample = {.ptr = getMyVar()};
}
But it cannot be used as an initialisation of the static storage variables

I am afraid you cannot. C language has only 3 scopes:
global scope is (potentially) visible to the whole program (across different compilation units)
static scope is visible to a compilation unit
local scope is visible to the block where the variable is declared
If you want to initialize a global or static variable, its initializers can only contain global or static symbols, which have to be visible throughout all the source file.

Related

C Programming Error: undefined symbol to a struct (Keil error L6218E)

I am using Keil MDK ARM to develop a project. However, when I am trying to build my code, the software tool throws the ERROR: L6218E : Undefined symbol Bit (referred from main.o).
Where Bit is a struct that I am using to store boolean values. For eg:
In variable.h file
struct
{
unsigned bPowerONStatus : 1;
unsigned bTimerONStatus : 1;
} extern Bit;
In main.c file:
#include variable.h
int main()
{
while(1)
{
ReadTimerStatus();
if(Bit.bPowerONStatus)
{
// System is ON
}
else
{
// System if OFF
}
}
}
In PowerChecker.c file
#include variable.h
void ReadTimerStatus(void)
{
if(Bit.bTimerONStatus)
{
Bit.bPowerONStatus = 1;
}
else
{
Bit.bPowerONStatus = 0;
}
}
What am I doing wrong here? What is the correct method of defining a struct, that will be used in multiple source files?
Declaring a variable at file scope with the keyword extern, but with no initializer declares the variable to have external linkage, but does not define the variable. There needs to be a definition of the variable elsewhere in your program.
In the case of your Bit variable, it has been declared with an anonymous struct type that has no type alias, so there is no way to use the same type when defining the variable. In order to fix that you need to either define the struct type with a tag, or define the struct type within a typedef declaration, or you can do both.
It is more conventional to put the storage class specifier such as extern at the front of the declaration.
In variable.h:
struct StatusBits
{
unsigned bPowerONStatus : 1;
unsigned bTimerONStatus : 1;
};
extern struct StatusBits Bits;
In only one C file, e.g. main.c or variable.c:
#include "variable.h"
struct StatusBits Bits;
Note that the struct StatusBits Bits; above has external linkage and has no initializer, but has not been declared extern, so it is a tentative definition of the Bits variable. Unless overridden by a definition of the same variable with an initializer, it will behave as if it has been initialized with {0}.

what is "struct <name_1> <name_2>" in c?

there is a line in c code:
struct name_1 name2;
what this line implies?
my understanding about above line is name_1 is the name of the structure and name2 is the object variable. However name_1 should have been defined somewhere, but I could not find the definition of name_1.
so my question is; is there anything like this where we can have an object of a structure which is not defined anywhere.
At file scope, this is the definition of a variable called name2 whose type is struct name_1. If there has not been a previous declaration of struct name_1; then this line also declares that type.
Being a file scope variable definition with no initializer nor storage class specifier, this is a tentative definition. Tentative definitions may have incomplete type so long as the type is completed by the end of the file, e.g.:
#include <stdio.h>
struct foo bar;
void f();
int main()
{
printf("%p\n", (void *)&bar);
f();
// cannot do this
// printf("%d\n", bar.x);
}
struct foo { int x; };
void f()
{
bar.x = 5;
}
This sort of code would be uncommon however. If you see struct foo bar; in real code it is more likely that struct foo was previously defined somewhere that you are overlooking.
Is there a header file (name.h) you have included in your c code? Usually, structure, constant and function declarations are in the header file, which is 'included' (at the top of your c file), and you could then use those structures and constants in your c file without defining them

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 static on typedef struct

I use the following code a lot in C:
typedef struct
{
int member;
} structname;
Now i'm trying to keep that struct definition local to a particular source file, so that no other source file even knows the struct exists. I tried the following:
static typedef struct
{
int member;
} structname;
but GCC whines because of an illegal access specifier. Is it even possible to keep a struct's declaration private to a source file?
If you declare the typedef struct within a .c file, it will be private for that source file.
If you declare this typedef in a .h file, it will be accesible for all the .c files that include this header file.
Your statement:
static typedef struct
Is clearly illegal since you are neither declaring a variable nor defining a new type.
All declarations are always local to a particular translation unit in C. That's why you need to include headers in all source files that intend to use a given declaration.
If you want to restrict the use of your struct, either declare it in the file in which you use it, or create a special header that only your file includes.
A structure definition is private to a source file unless placed in a shared header file. No other source file can access the members of the struct, even if given a pointer to the struct (since the layout is not known in the other compilation unit).
If the struct needs to be used elsewhere, it must be used only as a pointer. Put a forward declaration of the form struct structname; typedef struct structname structname; in the headerfile, and use structname * everywhere else in your codebase. Then, since the structure members appear only in one source file, the structure's contents are effectively 'private' to that file.
Hernan Velasquez's answer is the correct answer: there are several problems with your code snippet. Here's a counter-example:
/* This should go in a .h if you will use this typedef in multiple .c files */
typedef struct {
int a;
char b[8];
} mystructdef;
int
main (int argc, char *argv[])
{
/* "static" is legal when you define the variable ...
... but *not* when you declare the typedef */
static mystructdef ms;

Calling a function (linked in C)

I'm trying to call a function from a .h and another .c file
trying to call the function in a line like this:
image = getImage(filename,&dim);
I have defined image at the top of main function as,
QTnode* image;
from the struct
struct imgnode{
int numb; //number of the image
int dim; //dimension of the image
char filename[20]; //name of file
QTnode *qt;
Imgnode *next;
Imgnode *prev;
};
the function is in another .h called
QTnode *getImage(char *filename, int *dim );
but the compiler tells me filename is undeclared. Any help?
LOL i helped my friend working on this yesterday. COMP1917 assignment hmm?
you are supposed to pass in the filename you read from the stdin rather than the filename in the struct in this assignment
Back to C, defining a structure doesn't mean that you have that structure and have those members inside the structure. You still declare and create a structure instance by doing this:
struct imgnode node;
then you can access the member by doing this:
node.filename
or more commonly:
struct imgnode* nodePtr;
nodePtr->filename
image = getImage(filename,&dim);
// ^^^^^^^^ Check where this variable declared.
// If declared check whether it is accessible from this scope.
Compiler don't know what the variable filename being passed an argument in the current translation unit. filename should be some where declared and should be accessible at the point of the function call. Check it.
If you are trying to access the struct members then you should have instance to access them.
image = getImage(strucInstance.filename,&(strucInstance.dim) );
What you usually do is something like this
So you have a function defined in foo.c as
void foo()
{
/* do nothing */
}
You put this line in a header file - guarded by include guards
void foo();
Now you include that header file in your other c file and the function should be able to resolve at compile time

Resources