Why is it not returning a function? - c

I'm writing a program for converting temperatures and I have most of it written. When I compile and run the program, it doesn't do the calculations, doesn't seem to recognise the C/F choice and it isn't working out the reset part either.
What am I doing wrong?
#include <stdio.h>
#include <ctype.h>
float promptTemp(float kelvin)
{
printf("Please enter a sample temperature in degrees Kelvin:\n");
float convertFahrenheit(float temp)
{
}while(reset == 'y');
return(0);
}

The problem in your code is
promptTemp(temp);
and
promptConvert(convert);
you're neither
passing the pointer to variables as argument
collecting the return value.
So,
if(convert == 'c')
is esseentially using (reading) an uinitialized variable convert which in turn invokes undefined behaviour.

Please be aware that the values of the variables from your main function are changing inside your functions, because you are only passing a copy, and only that copy is modified inside the function and then lost. ( even though they have the same name ).
Try to pass the parameters as references or pointers.

You are not storing the return value of the function in the main function:
promptTemp(temp);/promptConvert(convert);
try result = promptTemp(temp);
and also you are not passing anything to the
promptTemp() function

There are a few things that need to be modified:
promptConvert(convert);
It isn't doing anything to convert variable. If you want the value returned from the function to be stored in the function, do this:
convert = promptConvert(convert);
If you want the function to modify the value of variable passed to it, do this:
char promptConvert(char &convert) //pass by reference
Similarly for other functions, like:
temp = convertCelsius(temp);
or
float convertCelsius(float &temp)
There are other functions which need the same modification too, like float convertFahrenheit(float temp)

By using a decent compiler, all the problems in this code will be revealed. One example of such a compiler is GCC. Get that one and then use it properly:
gcc -std=c11 -pedantic-errors -Wall -Wextra
Compiler output:
C:\tmp>gcc test.c -std=c11 -pedantic-errors -Wall -Wextra
test.c: In function 'promptConvert':
test.c:17:5: warning: statement with no effect [-Wunused-value]
tolower(convert);
^
test.c: In function 'promptReset':
test.c:72:5: warning: statement with no effect [-Wunused-value]
tolower(reset);
^
test.c: In function 'main':
test.c:87:9: warning: 'temp' is used uninitialized in this function [-Wuninitial
ized]
promptTemp(temp);
^
test.c:89:9: warning: 'convert' is used uninitialized in this function [-Wuninit
ialized]
promptConvert(convert);
^
test.c:100:9: warning: 'reset' is used uninitialized in this function [-Wuniniti
alized]
promptReset(reset);
^
So in addition to the bugs already pointed out in other answers, you also don't store the return value of tolower(). Should have been convert = tolower(convert);

Related

Warning: may be used uninitialized in this function

Hitting below warning with new gcc version 6.X
Warning: 'temp' may be used uninitialized in this function [-Wmaybe-uninitialized]
Code:-
int temp;
if (logcat (MSPRO_P->regs[test],
byte, &temp, test) == FALSE){
memErrorMsgHistoryVa (MSPRO_MEMP, "Invalid Data Count 0 value");
MSPRO_P->flashCmdError = TRUE;
}
gcc isn't supposed to warn about passing a pointer to an uninitialized variable to a function it doesn't know anything about (the assumption is that the function will initialize it). So I'm pretty sure that gcc knows things about logcat and the uninitialized use is detected in there. Maybe it got inlined or such.
Example:
$ cat > foo.c
static int
bar(int *a)
{
return *a + *a;
}
int
foo(void)
{
int x;
int y = bar(&x);
return x + y;
}
$ cc -Wall -c foo.c
$
Here, despite it being blindingly obvious to humans, gcc doesn't actually know what happens inside the function bar. So no warning.
Let's help gcc to understand what's going on:
$ cc -O1 -Wall -c foo.c
foo.c: In function ‘foo’:
foo.c:4:12: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
return *a + *a;
~~~^~~~
foo.c:10:6: note: ‘x’ was declared here
int x;
^
$
Just turning on optimization helped gcc to see what's going on (probably some inlining happened).
From the minimal piece of code you've shown and the warning message, where it looks like you cut out the bit that actually tells you exactly where in your code the problem happens, I conclude that the problem is in your logcat function.
temp is uninitialized after int temp;.
logcat (MSPRO_P->regs[test], byte, &temp, test)
Since a pointer to temp is passed to the function, we, as programmers can guess that this function is supposed to initialize temp. But that is very difficult, if not impossible, for the compiler to assert with absolute certainity, specially when that function is in separate translation unit. From compilers perspective, there is no easy way to tell whether logcat will write to *temp or read it first in uninitialized state. And that's why the warning.
The easiest way to get rid of this warning is assign some initial value to temp, like:
int temp = 0

printf() with incomplete parameter list

I was solving C programming Questions and I came across this
#include<stdio.h>
int main()
{
int x=100,y=200,z=300;
printf("%d..%d..%d");
}
I expected an error but the output was 300..200..100
Can anyone explain this output?
%d in printf expects int type argument. You are passing no arguments. Its a constraint violation and ultimately your program invokes undefined behavior.
your code has so many warning says..
root#jeegar:~/test# gcc -Wall testprintf.c
testprintf.c: In function ‘main’:
testprintf.c:5:4: warning: too few arguments for format
testprintf.c:4:20: warning: unused variable ‘z’
testprintf.c:4:14: warning: unused variable ‘y’
testprintf.c:4:8: warning: unused variable ‘x’
testprintf.c:6:1: warning: control reaches end of non-void function
when i run your code it shows different result each time.
root#jeegar:~/test# ./a.out
1822880072..1822880088..4195632root#jeegar:~/test#
root#jeegar:~/test#
root#jeegar:~/test# ./a.out
-1388515512..-1388515496..4195632root#jeegar:~/test#
root#jeegar:~/test#
root#jeegar:~/test#
root#jeegar:~/test# ./a.out
401499528..401499544..4195632root#jeegar:~/test#
So here it's undefined behavior
It may be posible that undefined behavior result same value as yours
printf is
int printf(const char*, ...)
a function with variable number of arguments. printf identify number of arguments using const char string - it count number of % signs. It takes first argument after const char argument and walks down the stack. It occasionally happened that local variables are situated just under function frame. But on other compilers and with other directives you will get other results, because in this case behaviour is undefined. For example, on my computer I get 0, 100, 200. On win VSE I get 0..0..random number in debug mode and rand.. 0 .. rand in release mode, etc.
When you use "%d" you are saying that a integer input should go there, but you never supply the integer to use. You need to add the integers as arguments after the string, like this:
#include<stdio.h>
int main()
{
int x=100,y=200,z=300;
printf("%d..%d..%d", x, y, z);
}
If you run printf("%d..%d..%d"); you will still get an output, but it will be some random un-initialized values.

C printf printing random number

I am very new to C Programming and have a doubt... I've been asked to find errors in certain segments of C code... and this segment has me a bit confused so would appreciate the help...
int main(void)
{
int myInt = 5;
printf("myInt = %d");
return 0;
}
As far as i understand there is nothing wrong in this code. What i wanna know is why is this statement printing out a random number ??
The output i get is
myInt = 1252057154
Would appreciate the help... Thanks
You should read more about C programming.
And you should enable all warnings and debugging when compiling. With GCC, this means gcc -Wall -Wextra -g (on Linux at least).
When compiling with
gcc -Wall -Wextra -g john.c -o john
I am getting the following warnings:
john.c: In function ‘main’:
john.c:4:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
john.c:4:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
john.c:4:5: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat]
john.c:3:9: warning: unused variable ‘myInt’ [-Wunused-variable]
So the correction is simple:
/* file john.c */
#include <stdio.h>
int main(void)
{
int myInt = 5;
printf("myInt = %d\n", myInt);
return 0;
}
which gets compiled without warnings.
Notice the \n at the end of printf format string. It is important.
Always enable all the warnings the compiler can give you and trust the compiler, so correct your code till no warnings is given.
And learn to use the debugger (e.g. gdb on Linux).
The behavior you observed is undefined behavior; anything could happen with a standard conforming implementation of C (even an explosion).
Happy hacking.
printf (and similarly scanf) works like this:
Let's say you issue a call to printf
printf("%d some text %f %u %hu some more text\n", arg1, arg2, arg3, arg4)
printf goes over the format string and replaces %? with an argument, based on ?
%d some text %f %u %hu some more text
| | | |
arg1 arg2 | arg4
arg3
Now the thing with functions taking variable number of arguments is that, they don't know if the arguments exist, that's why they just take data from a specific part of the stack based on the format string. If you write:
printf("%d %f %u\n");
it reads three non existing data from the stack, most probably get the values stored when calling the function (values that should be hidden from you)
Well, if it's printing something wrong, the problem is in the printf call:
printf("myInt = %d");
Which arguments you're expected to pass?
It should be this:
printf("myInt = %d",myInt);
If you don't include the variable, then it basically pulls a random chunk of memory in. In addition, it might cause more wierd stuff to happen if you do this with a larger chunk of code. Always make sure that you have as many variables from a printf statement as you need, or bad stuff will result.
printf is a function that receives one or more arguments.
In your case it received only one argument (which is legal) but the argument containes %d which tells printf to take the second argument instead of the %d.
printf takes the "second argument" from the stack, and because only one argument was pushed to the stack (the string), it uses the return address as the second argument.
int main(void)
{
int myInt = 5;
printf("myInt = %d",myInt);
return 0;
}
The only change in the code is I added myInt variable in the printf statement if you see at the end.Whenever a variable is assigned some value it can be displayed only by passing it to the printf() function with the corresponding type specifier.Its a rule in C.

Removal of warnings when I compile

This is a sample piece of code I am posting below. I am getting a warning when I compile this program as shown below:
samp2.c: In function `main':
samp2.c:37: warning: passing arg 1 of `my_func' from incompatible pointer type
The code is shown below:
typedef enum TES_status_e
{
TES_stat_unknown,
TES_stat_ok,
TES_stat_too_high,
TES_stat_too_low,
TES_stat_short_GND,
TES_stat_connected,
TES_stat_not_connected
} TES_status_t;
typedef enum DIAG_status_e
{
DIAG_stat_unknown,
DIAG_stat_ok,
DIAG_stat_too_high = 10,
DIAG_stat_too_low,
DIAG_stat_short_GND,
DIAG_stat_connected,
DIAG_stat_not_connected
} DIAG_status_t;
typedef int (*MyPtr)(TES_status_t);
int my_func(MyPtr);
int test(DIAG_status_t);
main()
{
my_func(&test);
}
int my_func(MyPtr Val)
{
Val(DIAG_stat_too_high);
}
int test(DIAG_status_t c)
{
printf("The val of c is %d\n",c);
}
This is the warning shown as below
samp2.c: In function `main':
samp2.c:37: warning: passing arg 1 of `my_func' from incompatible pointer type
Please let me know how to remove this warning.
You declared my_func to take a function that accepts a TES_status_t enum as argument however the actual test function takes a DIAG_status_t argument that is why you get a warning.
Also the function takes a function pointer, but a function name like test is in fact a function pointer so you only need to supply the function name, not the address:
my_func((MyPtr)test);
Wait, the warning looks like it's right to me.
Despite what you may think, TES_status_t is not equivalent to DIAG_status_t.
I recommend that you fix your code, not the warning.
GCC is right.
You define MyPtr as a pointer to a function that takes a TES_status_t argument and then supply a pointer to a function that takes a DIAG_status_t argument.
EDIT:
You can suppress the warning by explicitly casting to MyPtr: my_func((MyPtr)test);
However this is usually a recipe for disaster, because you essentially introduce non-obvious dependencies between types and the code that uses them.
True, enumerations in C are represented by an int type and in this case both enumerations seem to have a correspondence to each other. But what happens in two weeks when you decide to e.g. add a new state in DIAG_status_t? Your program will break subtly and you will have a hard time tracking the problem because you will have ignored what little type checking the compiler does for you.
my_func expects a pointer to a function taking TES_status_t value and returning an int.
You're calling it with a pointer to a function taking a DIAG_status_t and returning an int.
Edit the line 37 of your samp2.c file till you get no more warnings. Don't turn compiler warnings off, they are very useful. If using gcc, ask for (almost) all of them with -Wall.
A TES_status_t value is not a DIAG_status_t value (but don't think that casting TES_stat_too_high to a DIAG_status_t will give you DIAG_stat_too_high)

Print the name of function assigned to a function pointer

I need to print the name of functions which is already stored in a function pointer.
Eg.
preValidateScriptHookFunc = (srvScrGenFuncPtrType)SRV_VerifyPymtOrderMaintDtls_validate_data;
I want the value "SRV_VerifyPymtOrderMaintDtls_validate_data" as output during program run via preValidateScriptHookFunc.
preValidateScriptHookFunc is a function pointer which can store any function name.
Please let me know which format specifier should be used in printf or fprintf.
This is generally not possible - see http://c-faq.com/misc/symtab.html.
I'm afraid that without using debug info api (which depends on the platform your in) or using some kind clever trickery with register the pointer in a lookup table it is just not possible.
Depending on your compiler, you might be able to use a pre-defined macro.
http://msdn.microsoft.com/en-us/library/b0084kay(VS.71).aspx
As Ofir says in his answer, you basically cannot do that. The names of the functions only exist before linking is done (they may endure afterwards in debugging data). After link it's only pointers.
If you're willing to store the function addresses somewhere and compare to them, you can do somewhat like this:
$ cat 3922500.c
#include <stdio.h>
char *fxname(void *fx) {
if (fx == fprintf) return "fprintf";
if (fx == gets) return "gets";
if (fx == scanf) return "scanf";
return "(unknown)";
}
int main(void) {
void (*fx)(void);
fx = gets; printf("name: %s\n", fxname(fx));
fx = putchar; printf("name: %s\n", fxname(fx));
return 0;
}
$ gcc 3922500.c
3922500.c: In function 'main':
3922500.c:12: warning: assignment from incompatible pointer type
3922500.c:13: warning: assignment from incompatible pointer type
/tmp/ccvg8QvD.o: In function `fxname':
3922500.c:(.text+0x1d): warning: the `gets' function is dangerous and should not be used.
$ ./a.out
name: gets
name: (unknown)

Resources