The variable 'pminutes' is being used without being initialized - c

I keep getting this error message:
The variable 'pminutes' is being used without being initialized.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void ConvertMinutesToHM(int time_minutes, int *phours, int *pminutes);
void main ()
{
int min, *phours, *pminutes;
printf("Enter a number of minutes:\n");
scanf("%d", &min);
ConvertMinutesToHM(min, phours, pminutes);
printf("Hours=%d", phours);
printf("Minutes=%d", pminutes);
}
void ConvertMinutesToHM (int time_minutes, int *phours, int *pminutes)
{
int hours, minutes;
*phours = time_minutes / 60;
*pminutes = time_minutes % 60 * 60;
}

In the c programming language, variables that are not global or static or explicitly initialized by the programmer are not initialized at all and reading them would cause undefined behavior.
You are passing it to a function that will dereference the pointer and since it was not initialized the function would read from an undetermined location in memory, because the value the pointer is holding is not defined anywhere. This does not mean that the pointer is not holding a value, it means that the value is a random garbage value that cannot be used as an address but will be if you are not careful and dereference it.
You can initialize it by making it point to an actual variable that would be allocated on the stack and make it point to valid memory, the like this
int minutes;
int *pminutes = &minutes;
of course, you can simply pass &minutes directly but this way, the pminutes pointer will be holding the address of a stack variable minutes which is properly allocated, but uninitialized.
The minutes variable is not required to be initialized because it's intended to be used as storage for the value the function will read and store into whatever pminutes is pointing to.
The problem is then that pminutes is a pointer, and not initializing it will cause undefined behavior when the program attempts to read the address it is holding.
It's still good practice to explicitly initialize most variables, but I also consider good practice not to do it when you are certain that they will be initialized somewhere and adding a explicit initialization would not be meaningful, thus making the code harder to understand.

Because you haven't initialised pminutes in main before passing it to ConvertMinutesToHM() function. Remember you need to initialise all parameters before passing them to a function - otherwise how does the function know what values to work on?
In main you should really just need normal int and initialise them properly:
int min = 0, phours = 0, pminutes = 0;
In when calling ConvertMinutesToHM(), you can pass in the address of the corresponding variables:
ConvertMinutesToHM(min, &phours, &pminutes);
Edit: You made other mistakes, too in that ConvertMinutesToHM() function: local hours, minutes are completely not needed, and the calculation of pminutes makes no sense.
Sample fix:
void ConvertMinutesToHM(int time_minutes, int *phours, int *pminutes);
int main()
{
int min = 0, phours = 0, pminutes = 0;
printf("Enter a number of minutes:\n");
scanf("%d",&min);
ConvertMinutesToHM(min,&phours,&pminutes);
printf("Hours=%d\n",phours);
printf("Minutes=%d\n",pminutes);
}
void ConvertMinutesToHM (int time_minutes, int *phours, int *pminutes)
{
*phours=time_minutes/60;
*pminutes=time_minutes%60;
}

The following code:
cleanly compiles
performs the desired operation
incorporates the comments on the OPs question
and now the code
#include <stdio.h> // printf(), scanf(), perror()
#include <stdlib.h> // exit(), EXIT_FAILURE
//#include <math.h>
void ConvertMinutesToHM(int time_minutes, int *phours, int *pminutes);
int main ( void )
{
int min;
int hours;
int minutes;
printf("Enter a number of minutes:\n");
if( 1 != scanf("%d", &min) )
{
perror( "scanf failed to read the minutes from the user" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
ConvertMinutesToHM(min, &hours, &minutes);
printf("Hours=%d\n", hours);
printf("Minutes=%d\n", minutes);
} // end function: main
void ConvertMinutesToHM (int time_minutes, int *phours, int *pminutes)
{
//int hours, minutes;
*phours = time_minutes / 60;
*pminutes = time_minutes % 60;
} // end function: ConvertMinutestoHM
and here is the results that are displayed on the terminal:
Enter a number of minutes:
100
Hours=1
Minutes=40

You are using pointer that is uninitialised. Pointers with static storage are initialized with null pointers. Pointers with automatic storage duration are not initialized.
From C89 Standard:
C89 §3.5.7 Initialization
If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant. If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
See Also ISO C 99 6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. If an object that has static storage duration is not initialized explicitly,
then:
if it has pointer type, it is initialized to a null pointer;
You are defining int *pminutes and not initialising it so its value is indeterminate and after that doing *pminutes = time_minutes%60*60 try to access that indeterminate location and result in undefined behaviour.

Related

Why can we initialize inside a function and still use that value outside the function?

For example:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct {
int n;
double d;
} some_thing;
void alloc_and_init_some_thing(some_thing** s, int n, double d) {
some_thing si = { .n=n, .d=d };
*s = malloc(sizeof(**s));
memcpy(*s, &si, sizeof(**s));
}
void alloc_and_init_int(int **i) {
int j = 21;
*i = malloc(sizeof(**i));
memcpy(*i, &j, sizeof(**i));
}
int main() {
some_thing *s;
alloc_and_init_some_thing(&s, 41, 31);
printf("s->n=%d s->d=%f\n", s->n, s->d);
int *i;
alloc_and_init_int(&i);
printf("*i=%d\n", *i);
return 0;
}
I'm still learning C and the difference between the stack and the heap. When we declare and initialize the variable si in the function alloc_and_init_some_thing, doesn't this value exist on the stack? Hence it should get wiped out when the function finishes?
But I can see that that doesn't actually occur. Back in the main function, when we print s->n, we get the value 41.
Similarly, when we print the value for *i in the main function, it prints 21.
Why is that?
The line memcpy(*s, &si, sizeof(**s)); copies the the structure si on the stack into the heap allocated structure s, thus making it persist in memory as heap allocations can be accessed anywhere in the program. It's merely a pointer to an address in memory.
The same thing happens in the similar function.
You are right that the lifetime of "si" and "j" are limited to their respective functions and not available after the return from those functions. However, their contents have been replicated via malloc/memcpy prior to the return of the functions and the pointers to the replicas are stored in variables "s" and "i", which are still alive at the time of printing (or using) those replicas.

C: dynamic declare array size

I have the following declaration inside a function
int f[20000]
I want the number 20000 to be dynamic, How can i declare such array in code?
To be more specific, I have the following code to calculate PI.
#include <stdlib.h>
#include <stdio.h>
#define BITS 2000
int a=10000,b,c=BITS*7/2,d,e,f[BITS*7/2+1],g;
int main()
{
for(;b-c;)
f[b++]=a/5;
for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)
for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);
//getchar();
return 0;
}
I changed to
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
//
// .... omit some lines here
// read bits from user input at runtime
// say precision = 200
//
int a=10000,b,c=precision *7/2,d,e,f[precision *7/2+1],g;
for(;b-c;)
f[b++]=a/5;
for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)
for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);
//getchar();
return 0;
}
It doesn't work, I googled then changed to
int a=10000,b,c=precision *7/2,d,e,g;
int *f=calloc(precision *7/2+1, sizeof(int));
It still doesn't work, I mean the program doesn't crash, the value it calculated is not correct. What's wrong? Thank you.
There are two ways to achieve what you want.
use dynamic memory allocation. malloc()/calloc()
use variable-length array (in c99)
That said, as pointed out by #user3386109, the problem in your second code snippet is use of uninitiated variable b. You may want to explicitly initialize the local variables before using their value.
You get a dynamically sized array by allocating on the heap using malloc (or calloc).
Replace
int f[20000];
with
int *f = (int *) malloc(20000 * sizeof(int) );
The difference is that global variables are guaranteed to be initialized to 0 (unless initialized to some other value). But local variables are garbage unless you initialize them. So the problem is that variable b starts out as garbage in the second snippet.
In the original code:
int a=10000,b;
int main(void)
{
}
a will start with the value 10000 because you initialized it, and b will start as 0 because it is an uninitialized global variable.
In the changed code:
int main(void)
{
int a=10000,b;
}
a will start with the value 10000 because you initialized it, and b will start as some random value (e.g. 0x5315fe) because it is an uninitialized local variable.
Replace int f[2000]
with
int *f = new int[2000];
then use the array as f[0] = 1, f[1] = 2 etc...
when finished free up memory with delete [] f;
the array size could be allocated by a variable
eg.
int x = 2000;
f = new int[x];

Creating an array during run-time and passing it to a function in C?

I'm getting some input from the user in the main() function and create an array accordingly. Because of the nature of the location of this array it is not visible to other functions and I need to pass it to a few other functions for processing.
Is there any way to do this without allocating memory for it and passing a pointer to that allocated memory?
flight is structure typedef.
int main()
{
do{ // Read # of flights from user
printf("Enter max number of flights to read in from file\n");
printf("--> ");
fflush(stdin);
} while(!(scanf("%d",&num_of_flights)));
flight database[num_of_flights]; // Create database for flights
In C you can allocate memory during runtime in such way
#include <stdlib.h>
#include <stdio.h>
void print_array(int *array, int array_size){
for(int i = 0; i < array_size; ++i){
printf("%d ", *(array + i));
}
}
int main(){
int *array;
int array_size;
scanf("%d", &array_size);
array = malloc(sizeof(int) * array_size);
// Fill array with ints
for(int i = 0; i < array_size; i++){
*(array + i) = i;
}
print_array(array, array_size);
return 0;
}
This shows how you might use malloc on a struct and then use the malloc'd item as a parameter to other functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct fl {
int distance;
char aeroplane[30];
char startgeo[2];
};
typedef struct fl flight;
void show_flight_data(flight d) {
printf("distance %d aeroplane %s",d.distance, d.aeroplane);
}
int main()
{
int num_of_flights;
flight *database;
do{ // Read # of flights from user
printf("Enter max number of flights to read in from file\n");
printf("--> ");
fflush(stdin);
} while(!(scanf("%d",&num_of_flights)));
database=(flight *)malloc(sizeof(flight) * num_of_flights);
database[0].distance = 100;
database[1].distance = 200;
strcpy(database[0].aeroplane, "777");
strcpy(database[1].aeroplane, "Airbus");
show_flight_data(database[0]);
return(0);
}
From the C standard, 6.2.4 Storage durations of objects:
The lifetime of an object is the portion of program execution during
which storage is guaranteed to be reserved for it. An object exists,
has a constant address) and retains its last-stored value
throughout its lifetime....
An object whose identifier is declared with no linkage and without the
storage-class specifier static has automatic storage duration...
For such an object that does not have a variable length array type,
its lifetime extends from entry into the block with which it is
associated until execution of that block ends in any way.
So, the lifetime of database extends until the execution of its enclosing block ends. That block is the body of main, so it is alive until main returns or the program exits. Therefore, you can simply pass database to other functions, or even store its address in a global that is accessed by other functions ... there is no need to allocate space and copy it.
BTW, you should be aware that by defining database[num_of_flights], where num_of_flights is not a constant, you are using a relatively recent feature of C -- variable length arrays (VLA's) -- and that some prominent C compilers (cough, Visual Studio, cough) do not support them.

simple pointers to pointers

I know why this works:
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
*number = p;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
What I don't understand is why this doesn't (in my machine it prints 3700 or something like that).
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
int **x = &p;
number = x;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
Why aren't both equivalent?
both are evil as they capture the address of a stack variable.
Second one doesn't do what you expect because you are assigning directly to the parameter number, which is only temporary, the first one changes something the parameter number pointers to, which is the same thing as number in main points to.
I assume they're not equivalent because number is passed by value, on the stack, as is standard for function parameters. Any changes that you make directly to number inside of cool_number() are modifying the local copy on the stack, and are not reflected in the value of number in main().
You get around this in the first example by dereferencing number, which tells the computer to modify some specific location in memory that you also happen to have a pointer to back in main(). You don't have this in the second example, so all that happens is that you make the local number pointer point to somewhere else, without actually updating any memory location being referred to back in main(). Thus nothing you do shows up once you get back to main().
And since value is local to the cool_number() function, setting a reference to it that will be accessed after cool_number() returns isn't guaranteed to work and certainly shouldn't be used in any code outside of a trivial/toy example. But in this specific instance it's not really related to why you're seeing different results between the two pieces of code.
As I understand, in both cases, your code is wrong.
In the first case, you are returning an address to a variable allocated on stack, which will be deallocated as soon as the function returns.
In the second case, the error of the first case exists, plus you are passing number by value, so an updation to number will not get reflected in the caller function.
In 'C', arguments are always passed by value. So, you cannot update the argument passed as it is. For Ex:
int func(int a)
{
a = 5; // In this case the value 5 will not be reflected in the caller as what is updated is the local copy of a on the stack
}
int func(int *a)
{
*a = 5; // This update will show in caller as you are directly updating the memory pointed to by a
a = malloc(4); //This update will not show in caller as again you are updating the local copy of stack
}
#include <stdio.h>
void cool_number(int **number) {
int value = 42; /* this "value" hold 42 value,
and it lifetime is only in this function */
int *p = &value; /* here we get the address of "value" in memory */
*number = p;
}
int main () {
int *number;
cool_number(&number); /* after this function the "value" in memory had been recyled
and may be used by other program */
printf("number is %d\n", *number); /* so when we print value here it will be
a unpredictable value, somehow may be crash */
return 0;
}
both the same principle

What is wrong with this C code

I have a piece of code where I am trying to return the square of the value pointed to by *ptr.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
main()
{
int a=8,t;
t=square(&a);
printf("%d",t);
}
Its working fine for me but author of this code said it might not work because of following reason:
Because it's possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square!. The correct way to do is
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
I really wanted to know why he said like that?
The idea of the volatile keyword is exactly to indicate to the compiler that a variable marked as such can change in unexpected ways during the program execution.
However, that does not make it a source of "random numbers" - it just advises the compiler - what is responsible for actually changing the variable contents should be another process, thread, some hardware interrupt - anything that would write to the process memory but not inlined in the function where the volatile declaration finds itself. In "older times" (compilers with less magic) everything it did was preventing the compiler from caching the variable value in one of the CPU registers. I have no idea on the optimisations/de-optimistions strategies triggered by it by modern compilers - but it will at least do that.
In the absense of any such external factor, a "volatile" variable is just like any other. Actually - it is just like any other variable - as variables not marked as volatile can also be changed by the same external causes (but the compiled C code would not be prepared for that in this case, which might lead to incorrect values being used).
Since the question has an accepted and correct answer, I will be brief: here is a short program that you can run to see the incorrect behavior happening for yourself.
#include <pthread.h>
#include <math.h>
#include <stdio.h>
int square(volatile int *p) {
int a = *p;
int b = *p;
return a*b;
}
volatile int done;
void* call_square(void* ptr) {
int *p = (int*)ptr;
int i = 0;
while (++i != 2000000000) {
int res = square(p);
int root = sqrt(res);
if (root*root != res) {
printf("square() returned %d after %d successful calls\n", res, i);
break;
}
}
done = 1;
}
int main() {
pthread_t thread;
int num = 0, i = 0;
done = 0;
int ret = pthread_create(&thread, NULL, call_square, (void*)&num);
while (!done) {
num = i++;
i %= 100;
}
return 0;
}
The main() function spawns a thread, and modifies the data being squared in a loop concurrently with another loop calling the square with a volatile pointer. Relatively speaking, it does not fail often, but it does so very reliably in less than a second:
square() returned 1353 after 5705 successful calls <<== 1353 = 33*41
square() returned 340 after 314 successful calls <<== 340 = 17*20
square() returned 1023 after 5566 successful calls <<== 1023 = 31*33
First understand what's volatile: Why is volatile needed in C?
and then, try to find answer by yourself.
It's a game of volatile and hardware world. :-)
Read answer given by Chris Jester-Young:
volatile tells the compiler that your variable may be changed by other means, than the code that is accessing it. e.g., it may be a I/O-mapped memory location. If this is not specified in such cases, some variable accesses can be optimised, e.g., its contents can be held in a register, and the memory location not read back in again.
If there is more than one thread, the value the pointer points to might change inbetween statement "a = *ptr" and statement "b = *ptr". Also: you want the square of a value, why put it into two variables?
In the code you present then there is no way for the variable a that is defined in your main to be modified whilst square is running.
However, consider a multi-threaded program. Suppose that another thread modified the value to your your pointer refers. And suppose that this modification took place after you had assigned a, but before you had assigned b, in the function sqaure.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//the other thread writes to *ptr now
b = *ptr;
return a * b;
}
In this scenario, a and b would have different values.
The author is correct (if *ptr will be changed by other threads)
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//between this two assignments *ptr can change. So it is dangerous to do so. His way is safer
b = *ptr;
return a * b;
}
Because the value of the pointer *ptr might change between the first affection and the second one.
I don't think the value of *ptr can change in this code barring an extremely unusual (and non-standards-compliant) runtime environment.
We're looking at the entirety of main() here and it's not starting up other threads. The variable a, whose address we are taking, is a local in main(), and main() doesn't inform any other function of that variable's address.
If you added the line mysterious_external_function(&a); before the t=square(&a) line, then yes, mysterious_external_function could start a thread and diddle the a variable asynchronously. But there's no such line, so as written square() always returns a square.
(Was the OP a troll post, by the way?)
I see some answers with *ptr can be changed by other threads. But this cannot happen since *ptr is not a static data variable. Its a parameter variable and local and parameter variables being hold inside stack. Each thread has its own stack section and if *ptr has been changed by another thread, it should not effect the current thread's.
One reason why the result might not give the square can be an HW interrupt might happen before assigning b = *ptr; operation as indicated below:
int square(volatile int *ptr) {
int a,b;
a = *ptr; //assuming a is being kept inside CPU registers.
//an HW interrupt might occur here and change the value inside the register which keeps the value of integer "a"
b = *ptr;
return a * b;
}

Resources