I have a program distributed across a number of files. There are a number of functions which need access to a global array. The issue I'm having is that I don't know the size of the array before the program starts. It opens up a file and then downloads a number of points, and then the array is created with a corresponding size. But for the array to be global, it needs to be declared outside of the main function i.e. before I know the number of points.
What I've tried to do right now is:
file1.c:
#include <stdio.h>
#include "file3.h"
int useful[];
int main()
{
int useful[10];
int i;
for (i = 0; i < 10; i++) {
useful[i] = i+1;
}
SPN();
return 0;
}
file2.c:
#include <stdio.h>
#include "file3.h"
void SPN() {
int i;
for (i = 0; i < 10; i++) {
printf("%i\n", useful[i]);
}
}
file3.h:
extern int useful[];
extern void SPN();
What I'm getting in output is just a bunch of 0s. At first I was thinking that the second int useful[... in file1.c creates a new array with a different internal name, but that doesn't seem to make any sense considering that no segmentation fault is triggered by SPN() when it tries to access memory outside the arrays bounds (if useful[] creates an array and isn't changed, it has default size 1 i.e. < 10). Help?
The int useful[10]; isn't initializing the global int useful[]; or anything like that. It's a new variable, and with the loop here
for (i = 0; i < 10; i++) {
useful[i] = i+1;
}
You're modifying the second useful without touching the global one. This is then discarded at the end of the function.
Instead have a global variable like this:
int *useful;
And initialize it this way:
useful = malloc(sizeof(int)*10);
The declaration of useful inside the main is shadowing the external one.
This means that the values that you think are inserting (in the main) in the global variable are actually going into the local variable.
Take a look at the following article about shadowing for more info.
It might also be interesting to look at scope rules in C.
Related
I am working on an Eclipse IDE doing some embedded C programming and I am a bit stuck on how I should proceed. My incomplete code is below -
#define ARRAYSIZE 50
void pressure_data(int *var1, int var2)
{
var2 = ARRAYSIZE;
int i;
uint16_t pressure;
for (i = 0; i < var2; i++)
{
pressure = pressure_read();
var1++;
}
}
int main();
{
int array[ARRAYSIZE];
pressure_data(array, 50);
return 0;
}
I would like my 'main' to create a 1D array with a size 50 (defined by ARRAYSIZE)
Each element of this 1D would be populated by a uint16_t value 'pressure' which is assigned by a separate function called 'pressure_read();'
The loop in the 'pressure_data' function would capture a new value of 'pressure' which would then fill the next index of the 1D array in 'main' and so on until the array contains 50 different 'pressure' values
Currently, this code will capture 50 different values of 'pressure' and print them into the terminal on Eclipse but I have omitted those lines for simplicity's sake.
What is the best method of passing a result of a function 'pressure_data', into each index of an array in my main?
I am relative beginner when it comes to C but have been taking some time to learn and understand using pointers as I know they are often used in conjunction with arrays.
Any help would be greatly appreciated.
Since you already have size limit of fifty on your array, you might simplify things in your function calls. Following is one example of how you might perform your task.
#include <stdio.h>
#include <stdlib.h>
#define ARRAYSIZE 50
typedef unsigned short uint16_t;
uint16_t pressure_read()
{
/* For now just return an integer */
return 15;
}
void pressure_data(uint16_t var1[])
{
for (int i = 0; i < ARRAYSIZE; i++)
{
var1[i] = pressure_read();
}
}
int main()
{
uint16_t array[ARRAYSIZE];
pressure_data(array);
for (int i = 0; i < ARRAYSIZE; i++)
{
printf("Pressure: %d\n", array[i]);
}
return 0;
}
Note that in the function, the reference to a one-dimensional array is made in lieu of an integer pointer. Both are quite valid. The usage of the "[]" designation is just a point of preference. But this allows for some simplification of the population of the array.
Give that a try and see if this fulfils the spirit of your project.
I am reading a book on the C language ('Mastering C'), and found the topic on scope resolution operator (::) on page 203, on Google Books here.
But when I run the following code sample (copied from the book), the C compiler gives me an error. I searched on the internet but I am unable to find any reference to a scope resolution operator in C.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a);
printf("%d\n", ::a);
return 0;
}
So if I want to access a global variable then how could I do that from within the main() function ?
No. C does not have a scope resolution operator. C++ has one (::). Perhaps you are (or your book is) confusing C with C++.
You asked how you could access the global variable a from within a function (here main) which has its own local variable a. You can't do this in C. It is lexically out of scope. Of course you could take the address of the variable somewhere else and pass that in as a pointer, but that's a different thing entirely. Just rename the variable, i.e. 'don't do that'
No, namespaces are a feature of C++.
It is, however, possible to refer to global a in your example.
You can achieve this by using the extern keyword:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
printf("%d\n",a);
{ // Note the scope
extern int a; // Uses the global now
printf("%d\n", a);
}
return 0;
}
That's a bit tricky, though. It's bad style. Don't do that.
:: operator is available in C++ not C. If you wanted to access the global variable, use
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a); //prints 10
{
extern int a;
printf("%d", a); //prints 50
}
return 0;
}
Or you could use a pointer which holds the address of the global variable a and then dereference the pointer if you want to print the value of the global variable a.
No (the :: operator is C++ specific). In C, if you use the same identifier in different overlapping scopes (say, file scope a and block scope a), the block scope identifier shadows the file scope identifier and there is no way to refer to the shadowed identifier.
It is generally best programming practice to avoid shadowed variables. Many lint type programs can warn about this situation.
In plain C, there is no scope resolution. You have to name your variables differently.
That means that all variables a below are different ones:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
{
int a = 20;
int i;
for (i = 0; i < 10; i++) {
int a = 30;
}
}
return 0;
}
You may use pointers to access and edit global variables in C.
#include <stdio.h>
#include <stdlib.h>
int a;
a=78;
int *ptr=&a; //pointer for global a
int main()
{
int a=0;
printf("%d",a); //Prints 0 as local variable
printf("%d",*ptr);
ptr=30; //changes the value of global variable through pointer
printf("%d",*ptr); //Now it prints 30
return 0;
}
It entirely depends on what kind of compiler you're using to execute your code.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d\n",a);
printf("%d\n", ::a);
return 0;
}
Try running this code in Turbo C compiler, and you will get the results.
Now, regarding the C book that you're following, the examples codes present in the book must be in terms with Turbo C/C++ compiler and not the gcc compiler.
I have two files, main.c and main2.c. My experience tells me that they should do exactly the same, but they do not.
main.c declares a global variable outside the main routine. Then, inside the main routine, a pointer is declared and defined to point to that global variable. The global variable is changed, and the value of the local variable is printed to screen.
main2.c does the same, but convolutes local-to-global definition and change of global variable value into another function, change_number.
I cannot understand why this approach fails. main.c and main2.c are the boiled down results from a few hours of bugs fixing, documentation and tutorial reading and, obviously, reading here on SO.
My understanding of pointers is what I would call rudimentary: It points to a memory location. In case of a regular variable, the pointer would point to the memory location of that variable. Several pointers can point to the same memory location, but one pointer cannot point to several locations.
There's no such thing as pass-by-reference in C, but, as far as I know, this is not pass by reference since all variable and pointers are defined outside the function. Please enlighten me.
//File: main.c
#include <stdio.h>
#include <stdlib.h>
int global_number;
int main() {
int *local_number;
local_number = &global_number;
global_number = 9;
printf("local_number = %d\n", *local_number);
return 0;
}
Output: "local_number = 9". This is the expected result.
//File: main2.c
#include <stdio.h>
#include <stdlib.h>
int global_number;
void change_number(int *number) {
number = &global_number;
global_number = 9;
}
int main() {
int *local_number;
change_number(local_number);
printf("local_number = %d\n", *local_number);
return 0;
}
Output: "Segmentation fault". This is obviously not intended. The code runs fine right up until printf().
you never initialize local_number in the second program. It does not point anywhere, and will crash when accessed. Try
int *local_number = &global_number;
then the value should change
To have change_number also initialize local_number, pass the address of local_number and change the pointed-to pointer:
void change_number( int **number ) {
*number = &global_number;
global_number = 9;
}
...
int *local_number;
change_number(&local_number);
I am having trouble getting the ROBX and ROBY variables to print in the main function. This is a small portion of my program and I do not know what I am doing wrong. Thanks!
#include <stdio.h>
#include <time.h>
#define ROW 8
#define COLUMN 8
int robot (int m[ROW][COLUMN], int ROBX, int ROBY);
int ROBX;
int ROBY;
int main(void)
{
printf("%d %d\n", ROBX, ROBY);
return 0;
}
int robot (int m[ROW][COLUMN], int ROBX, int ROBY)
{
// ensure different output each time program is run
srand ( time(NULL) );
// Pick a random spot to place the robot
int placed = 0;
int ROBX;
int ROBY;
while(placed == 0)
{
int t = rand() % ROW;
int y = rand() % COLUMN;
if(m[t][y] == 0)
{
m[t][y] = -2;
placed = 1;
ROBX = t;
ROBY = y;
}
return ROBX, ROBY;
}
}
There are several problems with your code.
For one thing, you never call robot, so none of those modifications to your variables are happening.
For another, you're not allowed to return multiple values from a function: The line return ROBX, ROBY; is NOT doing what you think it's doing.
Finally, your function doesn't make a lot of sense. You intend to pass in ROBX and ROBY as parameters. That won't work the way you think it will, but it's not a terrible idea in general. But when you create local variables also called ROBX and ROBY. As commenters have noted, that will hide both the global variables and the parameters, so you end up only modifying those locally-defined variables.
There are two ways you can fix this:
Don't create local variables and don't pass parameters. Just modify the global variables directly.
Still don't create local variables, and make your function accept two int * parameters. This will allow you to pass in the global variables when you call robot, so you can modify those parameters in a persistent way. See this question for more details.
In either case, you will need to actually call your robot function.
I just want to understand the difference in RAM allocation.
Why if i define a variable before function i have a RAM overflow and when i define it inside a function it is ok?
For example:
/*RAM OK*/
void Record(int16_t* current, int i,int n)
{
float Arr[NLOG2] = {0};
for(i=0;i<n;i++)
Arr[i]=current[i*5];
}
/*RAM OVERFLOW*/
static float Arr[NLOG2] = {0};
void Record(int16_t* current, int i,int n)
{
for(i=0;i<n;i++)
Arr[i]=current[i*5];
}
This is the message:
unable to allocate space for sections/blocks with a total estimated
minimum size of 0x330b bytes (max align 0x8) in
<[0x200000c8-0x200031ff]> (total uncommitted space 0x2f38).
The difference is that in the first case, Arr is declared on the stack; until the function is called, that array doesn't exist. The generated binary contains code for creating the array, but the array itself isn't in the binary.
In the second case, however, Arr is declared outside of any function (aka at file scope). Therefore, it always exists, and is stored in the binary. Because you appear to be working on an embedded platform, this otherwise insignificant difference causes your "RAM overflow" error.
In the 2nd case, the array is allocated when the application starts. It remains in the memory until the app quits.
In the 1st case, the array is only allocated when function void Record(int16_t* current, int i,int n) is called. The array is gone after the function finishes its execution.
static keyword doesn't have any impact if you have only a single compilation unit (.o file).
Global variables (not static) are there when you create the .o file available to the linker for use in other files. Therefore, if you have two files like this, you get name collision on a:
a.c:
#include <stdio.h>
int a;
int compute(void);
int main()
{
a = 1;
printf("%d %d\n", a, compute());
return 0;
}
b.c:
int a;
int compute(void)
{
a = 0;
return a;
}
because the linker doesn't know which of the global as to use.
However, when you define static globals, you are telling the compiler to keep the variable only for that file and don't let the linker know about it. So if you add static (in the definition of a) to the two sample codes I wrote, you won't get name collisions simply because the linker doesn't even know there is an a in either of the files:
a.c:
#include <stdio.h>
static int a;
int compute(void);
int main()
{
a = 1;
printf("%d %d\n", a, compute());
return 0;
}
b.c:
static int a;
int compute(void)
{
a = 0;
return a;
}
This means that each file works with its own a without knowing about the other ones.