Assign a value to external variable from function - c

I've been reading here a lot but never posted until now.
My problem is that I'm stuck with some code. What I'm trying to do is receive a value through UART from Matlab and assign to a single variable that is gonna stick through the entire program.
This is the test code I'm running:
void start_comm(){
//Stuck in loop untill Matlab gives signal
// Spams character 'A' while waiting
while (!uart_is_rx_ready (CONF_UART)){
printf("%c\n",'A');
delay_ms(100);
}
// Start reading data sent from Matlab
// P,I,D & samplingstime data
uint8_t p_char, i_char, d_char, samp_char1, samp_char2;
while (!uart_is_rx_ready (CONF_UART)){};
uart_read(CONF_UART, &p_char);
// Print out everything out again for testing
printf("%c\n", p_char);
}
This code works, everything prints out fine. What I need is to be able to use the value in p_char in other functions and I need it to be the same value as the one sent from Matlab i.e. if it's 5 then I could printf in another function and it would print a 5.
I've tried return p_char to a different variable but it would just revert to 0 at the start of the loop. I've also tried the following test code where I try to set the variable as static:
**file1.h**
extern int a;
**file1.c**
#include file1.h
void function(){
static int a;
scanf("%i", &a);
}
**main.c**
#include file1.h
int main() {
function();
while(1){
printf("%i", a);
}
}
Looking over the code, I'm pretty sure I'm doing something wrong with the static and extern, but I'm lost.
EDIT: Figured out the problem, it was indeed Matlab code. I needed to add a delay to it to account for the time it took to communicate with the microcontroller.

Update your file1.c to read:
#include file1.h
int a;
void function(){
scanf("%i", &a);
}
This puts a in the global scope. If you keep extern int a in your .h file, C files that include that header will know about it.

Related

Global variables in C on STM32

I'm working on a project where I need to use one variable declared in a certain file (say mylib.c) in the main function using 'extern'. All headers are included with guard words to avoid multiple inclusions.
The variable is a structure(defined in mylib.h) which members are only floats and integers.It's initialized at the beginning of the main function.
After entering the main's loop, and doing some work, some members that aren't concerned get random values.
So,I removed extern from the declaration in main, and instead placed it in the declaration in mylib.c. And it worked.
Sim808.h
#ifndef _SIM808_H
#define _SIM808_H
typedef struct{
uint8_t GPRS_Active;
float gsm_latitude;
float gsm_longitude;
}SIM808;
void sendCmd(const char cmd[]);
void sim808_init(void);
void parse_gsm_location(uint8_t* line);
#endif
Sim808.c
#include "sim808.h"
SIM808 sim808;
void parse_gsm_location(uint8_t* line)
{
uint8_t commas=0,index=0;
uint16_t err;
if((err=atoi((const char*)line+12))!=0)
{
printf("No coordinates received\n");
if(err==404 || err==601)
sim808.GPRS_Active=0;
return;
}
while (line[index]!= '\0' && index <50)
{
if(line[index]==',')
{
commas++;
switch (commas)
{
case 1:
sim808.gsm_longitude=atof((const char*)(line+index+1));
printf("Long:%f\n",sim808.gsm_longitude);
break;
case 2:
sim808.gsm_latitude=atof((const char*)(line +index+1));
printf("Longitude%f Latitude%f\n",sim808.gsm_longitude,sim808.gsm_latitude);
break;
case 3:
sscanf((const char*)(line+index+1),"%4d/%2d/%2d", (int*)&sim808.gsmDate.year,(int*)&sim808.gsmDate.month,
(int*)&sim808.gsmDate.day);
break;
case 4:
sscanf((const char*)(line+index+1),"%2d/%2d/%2d",
(int*)&sim808.gsmTime.hours,(int*)&sim808.gsmTime.minutes,(int*)&sim808.gsmTime.seconds);
break;
}
}
index++;
}
}
main.c
#include "sim808.h"
extern SIM808 sim808;
int main(void)
{
uint8_t response[150];
//init functions
while(1)
{
if(sim808.GPRS_Active==1)
{
sendCmd("AT+CIPGSMLOC=1,1\r\n");
HAL_UART_Receive(&huart4,response,2,60000);//max response time is 1 min
HAL_UART_Receive(&huart4,response,150,1000);//we dont need first 2 chars
parse_gsm_location(response);
memset((void*)response,0,150);
}
else
sim808_init();
}
}
As you can see,the member GPRS_Active can only receive 1 or 0 in my code.
Using printf, it turned to become 242 after the first iteration.
Can someone explain? Can this be a compiler bug?
Thanks.
The chance it is a compiler issue is really small. More likely is that your variable is modified by some part of your code. Try to avoid using global variables as they have the largest scope.
Do you use somewhere local variable with same name?
Have you checked map file or in debugger where it is placed?
You can use debugger feature datawatch where you break if data at certain address changes to help you track this issue.
When I use global variables, I do not declare them in the .h file to avoid issues of multiple inclusions. You can of course find some tricks to declare them in the .h, but I think it makes things so complicated. So try this:
In mylib.c:
int myGlobalVariable;
In main.c
extern int myGlobalVariable;
int main(void)
{
myGlobalVariable = 5;
}
If you still have issues, try to increase the size of your stack. If the stack is not big enough, it could be overwritten by other data.
If you use memset or memcpy in any of your code, make sure that the length parameter is correct. memset and memcpy are quite dangerous and you could easily write in some part of the memory that you don't really want.

Counting the number of function calls in an executable

I am trying to find the exact number of function calls to one of my implemented C function inside my code. The project includes several C files. What is the easiest solution to figure out how many times a function is called during the execution of the program? Specifically, I am interested to know how many times a specific function calls another function. For instance I have a C file like:
//file1.c
int main(){
foo1();
return 0;
}
and other C files like:
//file2.c
void foo1(){
foo2();
...
foo2();
}
and
//file3.c
void foo2(){
foo3();
foo3();
foo3();
}
Now I have my final executable a.out and want to know how many times foo3() is called inside foo1().
BTW, I am compiling and running my project on Linux.
You can use 2 global variables (put extern at the places that access the variable outside the file you declare them) :
int foo1_active = 0;
int foo3_counter = 0;
then each time foo1 is called you increment it variable and before the return you decrement it:
void foo1() {
foo1_active++;
...
foo1_active--;
return
}
when foo3 is called you check if foo1 active and if it does you increment the counter:
void foo3() {
if foo1_active > 0 {
foo3_counter++;
}
...
}
You have an ubuntu flag, so I assume you are using gcc. I'd strongly consider adding -pg to your CFLAGS and trying out gprof.
Profiling works by changing how every function in your program is
compiled so that when it is called, it will stash away some
information about where it was called from. From this, the profiler
can figure out what function called it, and can count how many times
it was called. This change is made by the compiler when your program
is compiled with the `-pg' option, which causes every function to call
mcount (or _mcount, or __mcount, depending on the OS and compiler) as
one of its first operations.
You can count function calls using a static variable instead of global variable.
int inc(){
static int counter = 1;
counter++;
return counter;
}
int main(){
int i;
for (i = 0; i < 10; i++)
printf("%d\n", inc());
return 0;
}

C float reset to 0 after passing it to a function

In the code below,the variable "tmpRes" is correct before the call of "BuildCMD"
but inside this function,it loose his correct value and sets to 0,why it just doesn't keep the correct value even inside the BuildCMD function?
Calling code:
//tmpRead just an array of integer
float tmpRes=0;
Evaluate(tmpRead[3],tmpRead[4],tmpRead[5],&tmpRes);
printf("PRE : %f\n",tmpRes); //correct result
char *dataBuff=BuildCMD(RES,tmpData,tmpRes);
Evaluate code:
int Evaluate(int num1,int op,int num2,float *Res)
{
float tmpRes=0;
switch(op)
{
case(int)'+':{tmpRes=num1+num2;break;} //same with *Res=....
case(int)'-':{tmpRes=num1-num2;break;}
//etc...
}
*Res=tmpRes;
return 0;
}
BuildCMD:
char* BuildCMD(enum CMD cmd,int *values,float result)
{
//here the result is ALWAYS 0
//even if it was corrent before the call of BuildCMD
printf("IN: %f\n,result);
fflush(stdout);
//...rest of the code
}
Thanks in advance.
Yes,the application is multi threaded,i create n instances of mainClient from the server.
Links to the sourcecode (the one i wrote above is simplified).
mainClient.c
Utilities.c
It sounds like the code that calls BuildCMD does not have a proper prototype for that function.
You need this prototype either in main.c or in a .h file that main.c includes:
char* BuildCMD(enum CMD cmd,int *values,float result);
You have float tmpRes=0; inside Evaluate(). So in fact the Evaluate() doesn't use the global tmpRes. The global tmpRes remain 0 even though you pass it into Evaluate().

Is it possible to exchange a C function implementation at run time?

I have implemented a facade pattern that uses C functions underneath and I would like to test it properly.
I do not really have control over these C functions. They are implemented in a header. Right now I #ifdef to use the real headers in production and my mock headers in tests. Is there a way in C to exchange the C functions at runtime by overwriting the C function address or something? I would like to get rid of the #ifdef in my code.
To expand on Bart's answer, consider the following trivial example.
#include <stdio.h>
#include <stdlib.h>
int (*functionPtr)(const char *format, ...);
int myPrintf(const char *fmt, ...)
{
char *tmpFmt = strdup(fmt);
int i;
for (i=0; i<strlen(tmpFmt); i++)
tmpFmt[i] = toupper(tmpFmt[i]);
// notice - we only print an upper case version of the format
// we totally disregard all but the first parameter to the function
printf(tmpFmt);
free(tmpFmt);
}
int main()
{
functionPtr = printf;
functionPtr("Hello world! - %d\n", 2013);
functionPtr = myPrintf;
functionPtr("Hello world! - %d\n", 2013);
return 0;
}
Output
Hello World! - 2013
HELLO WORLD! - %D
It is strange that you even need an ifdef-selected header. The code-to-test and your mocks should have the exact same function signatures in order to be a correct mock of the module-to-test. The only thing that then changes between a production-compilation and a test-compilation would be which .o files you give to the linker.
It is possible With Typemock Isolator++ without creating unnecessary new levels of indirection. It can be done inside the test without altering your production code. Consider the following example:
You have the Sum function in your code:
int Sum(int a, int b)
{
return a+b;
}
And you want to replace it with Sigma for your test:
int Sigma(int a, int b)
{
int sum = 0;
for( ; 0<a ; a--)
{
sum += b;
}
return sum;
}
In your test, mock Sum before using it:
WHEN_CALLED: call the method you want to fake.
ANY_VAL: specify the args values for which the mock will apply. in this case any 2 integers.
*DoStaticOrGlobalInstead: The alternative behavior you want for Sum.
In this example we call Sigma instead.
TEST_CLASS(C_Function_Tests)
{
public:
TEST_METHOD(Exchange_a_C_function_implementation_at_run_time_is_Possible)
{
void* context = NULL; //since Sum global it has no context
WHEN_CALLED(Sum (ANY_VAL(int), ANY_VAL(int))).DoStaticOrGlobalInstead(Sigma, context);
Assert::AreEqual(2, Sum(1,2));
}
};
*DoStaticOrGlobalInstead
It is possible to set other types of behaviors instead of calling an alternative method. You can throw an exception, return a value, ignore the method etc...
For instance:
TEST_METHOD(Alter_C_Function_Return_Value)
{
WHEN_CALLED(Sum (ANY_VAL(int), ANY_VAL(int))).Return(10);
Assert::AreEqual(10, Sum(1,2));
}
I don't think it's a good idea to overwrite functions at runtime. For one thing, the executable segment may be set as read-only and even if it wasn't you could end up stepping on another function's code if your assembly is too large.
I think you should create something like a function pointer collection for the one and the other set of implementations you want to use. Every time you want to call a function, you'll be calling from the selected function pointer collection. Having done that, you may also have proxy functions (that simply call from the selected set) to hide the function pointer syntax.

short function in c - don't understand what's wrong

I'm writing a function that just calculates the "complementary" strand of DNA, meaning replaces C with G, T with A, and so on.
this is what I wrote:
#include <stdio.h>
#include <string.h>
#define SIZE 70
int isLegitSequence(char sequence[]);
void getComplementaryStrand(char complementary[],char sequence[]);
int findSubSequence(char sequence[],char subsequence[]);
int findSubComplementary(char sequence[],char subcomplementary[]);
void cutSequence(char sequence[],char tocut[]);
void checkDNAList(char data[][SIZE],int rows,char sequence[]);
void main(){
char dnaSequence[SIZE];
char compDnaSequence[SIZE];
printf("Enter a DNA Strand\n");
gets(dnaSequence);
printf("%d\n",isLegitSequence(dnaSequence));
getComplementaryStrand(compDnaSequence,dnaSequence);
puts(compDnaSequence);
}
int isLegitSequence(char sequence[]){
int i=0;
while (sequence[i]){
if(sequence[i]=='A'||sequence[i]=='C'||sequence[i]=='G'||sequence[i]=='T');
else return 0;
i++;
}
return 1;
}
void getComplementaryStrand(char complementary[SIZE],char sequence[SIZE]){
int j=strlen(sequence)-1,i;
for(i=0;sequence[i];i++,j--){
if(sequence[i]=='A') sequence[j]='T';
else if(sequence[i]=='C') sequence[j]='G';
else if(sequence[i]=='G') sequence[j]='C';
else sequence[j]='A';
}
complementary[strlen(sequence)]='\0';
}
However, this is what I get when I run the program:
Enter a DNA Strand
CGCTC
1
╠╠╠╠╠
Press any key to continue . . .
This is my first time using functions, so I'm not sure what I did wrong here.
Would appreciate help, but in the scope of my understanding, namely very very basic.
You need to add a prototype of the function getComplementaryStrand at the top of of the source file where the function is called.
Add this line at the top of the source file:
void getComplementaryStrand(char complementary[SIZE],char sequence[SIZE]);
EDIT: the question has changed in the meantime... Before it was a compilation error. OP please ask a new question instead of editing your original question with a new question.
Take a careful look at your for loop within your getComplementaryStrand() function. Are you assigning values to the correct string? I think not.
In getComplementaryStrand() you never fill anything in complementary string except end character. So you get garbage.

Resources