Symbolic Constant in Xcode - c

I'm learning C through The C Programming Language 2nd Edition and it refers to symbolic constants where you use #define before main() to assign a label to a value.
This is the program I am trying to use:
#include <stdio.h>
#define LOWER 0
#define UPPER 300
#define STEP 20
main()
{
int fahr;
for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP)
{
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
}
Printing a table of Fahrenheit Celsius conversions. However This code when compiled in xcode using the c tool gives me the response unable to read unknown load command referring to the line starting with for. I've tried retyping the program but it still hasn't worked. Any help would be much appreciated.

The first line should be
#include <stdio.h>

The code is perfectly fine. There's something wrong with your XCode setup (may be related: unable to read unknown load command.
cristi:tmp diciu$ cat test.c
#include <stdio.h>
#define LOWER 0
#define UPPER 300
#define STEP 20
main()
{
int fahr;
for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP)
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
cristi:tmp diciu$ gcc test.c
cristi:tmp diciu$ ./a.out
0 -17.8
20 -6.7
40 4.4
[..]

Works for me in XCode - the only warning/error I got was
Control reaches end of non-void function
As defining main() defaults to int it should return something, eg. 0 for a successful program. Convention suggests that 0 means a program runs correctly and anything else is an error.
Better to define
int main()
{
/* code */
return 0;
}
as your main function. But this is a digression - see diciu's answer for a potential explanation of your problem

Related

Why is my pdb file missing symbols when I link object files?

I'm compiling a very simple C program with two source files.
File 1:
#include <stdio.h>
#include "conv.h"
/* print Fahrenheit-Celsius table
for fahr = 0, 20, ..., 300 */
int main()
{
int fahr;
float celsius;
int lower, upper, step;
lower = 0; /* lower limit of temperature table */
upper = 300; /* upper limit */
step = 20; /* step size */
fahr = lower;
while (fahr <= upper) {
celsius = f2c(fahr);
printf("%d\t%0.2f\n", fahr, celsius);
fahr = fahr + step;
}
return 0;
}
File 2:
#include "conv.h"
/* Convert Fahrenheit to Celsius */
float f2c(int fahr) {
float celsius;
celsius = (fahr-32) * (5.0 / 9.0);
return celsius;
}
/* Convert Celsius to Fahrenheit */
float c2f(int cel) {
float fahr;
fahr = cel * (9.0 / 5.0) + 32;
return fahr;
}
I'm 'debugging' the program in windbg, although the program runs fine -- it's for experimentation. I'm compiling using the command-line Developer Command Prompt for VS 2019 in two ways. In the first case, I run the whole thing through CL:
cl /Zi /Fd:fahr fahr.c conv.c
and in the second case, I'm compiling without linking, then linking the object files:
cl /c fahr.c conv.c
cl /Zi /Fd:fahr fahr.obj conv.obj
In the first case, I can debug in windbg just fine. I open the executable, set a breakpoint, run it, and up comes my source file. But when I compile the second way, windbg will no longer connect to my source, and it fails to find variables in fahr.c and conv.c. As far as I can tell, everything is the same except for the circumstances when I link. What am I missing?
The debug file (.pdb) is added to in stages as each part of the program is built. When you compile files, the compiler adds their symbols to the pdb file (if you ask it to). Then, when you link files, it adds further symbols to the pdb file. I wasn't getting source file symbols because I didn't generate any debug data when I compiled the object files. The fix is:
cl /c /Zi /Fd:fahr fahr.c conv.c
cl /Zi /Fd:fahr fahr.obj conv.obj
My mistake was that I thought the debug file was generated by the linker only, which never sees the source files. Rather both the compiler and the linker have a role in producing the debug file.

Format modifier and percentage symbol issues

First question
#include <stdio.h>
int main(void)
{
int k;
printf("hello\n%n", &k);
printf("k: %d", k);
return 0;
}
The above code executes fine in Linux terminal and yields k: 6. When I execute that code on Windows using Code::Blocks, k returns a value that looks like a memory address. A sample output using Windows 10:
hello\n
k: 4123991
I looked up Code::Blocks 16.01 setting->compiler then in 'compiler flags' tab I could not find any useful check-box button that will fix the problem I describe.
What am I doing wrong? I want to see k=6 not k=4123991 when I execute that code using Windows and Code::Blocks (build->build and run, F9 button).
Second question
#include <stdio.h>
int main(void)
{
int k = 5;
printf("%*%\n",k);
return 0;
}
I was expecting to see k-1 spaces followed by a % symbol. Sadly, I see a % and no leading spaces at all. What am I ignoring?

Weird C program behaviour

I have the following C program:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
int main() {
const int opt_count = 2;
int oc = 30;
int c = 900;
printf("%d %f\n", c, pow(oc, opt_count));
assert(c == (int)(pow(oc, opt_count)));
}
I'm running MinGW on Windows 8.1. Gcc version 4.9.3. I compile my program with:
gcc program.c -o program.exe
When I run it I get this output:
$ program
900 900.000000
Assertion failed: c == (int)(pow(oc, opt_count)), file program.c, line 16
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
What is going on? I expect the assertion to pass because 900 == 30^2.
Thanks!
Edit
I'm not using any fractions or decimals. I'm only using integers.
This happens when the implementation of pow is via
pow(x,y) = exp(log(x)*y)
Other library implementations first reduce the exponent by integer powers, thus avoiding this small floating point error.
More involved implementations contain steps like
pow(x,y) {
if(y<0) return 1/pow(x, -y);
n = (int)round(y);
y = y-n;
px = x; powxn = 1;
while(n>0) {
if(n%2==1) powxn *= px;
n /=2; px *= px;
}
return powxn * exp(log(x)*y);
}
with the usual divide-n-conquer resp. halving-n-squaring approach for the integer power powxn.
You have a nice answer (and solution) from #LutzL, another solution is comparing the difference with an epsilon, e.g.: 0.00001, in this way you can use the standard function pow included in math.h
#define EPSILON 0.0001
#define EQ(a, b) (fabs(a - b) < EPSILON)
assert(EQ((double)c, pow(oc, opt_count)));

C program to find roots error

I am writing a function in C with the below specifications:
float find_root(float a, float b, float c, float p, float q);
find_root takes the coefficients a,b,c of a quadratic equation and an interval (p, q). It will return the root of this equation in the given interval.
For example: find_root(1, -8, 15, 2, 4) should produce a root "close to" 3.0
I have written the below code, and I don't understand why it doesn't work:
#include<stdio.h>
#include<math.h>
main()
{
printf("Hello World");
}
float find_root(float a, float b, float c, float p, float q) {
float d,root1,root2;
d = b * b - 4 * a * c;
root1 = ( -b + sqrt(d)) / (2* a);
root2 = ( -b - sqrt(d)) / (2* a);
if (root1<=q || root1>=p)
{
return root1;
}
return root2;
}
Please let me know what the error is.
Your program doesn't work, because, you never called find_root() from your main().
find_root() is not suppossed to run all-by-itself. Your program statrs execution from main(). You need to call your sub-function from main() in order to make them execute.
Change your main to have a call to find_root(), something like below.
int main() //put proper signature
{
float anser = 0;
answer = find_root(1, -8, 15, 2, 4); //taken from the question
printf("The anser is %f\n", answer); //end with a \n, stdout is line buffered
return 0; //return some value, good practice
}
Then, compile the program like
gcc -o output yourfilename.c -lm
Apart from this, for the logical issue(s) in find_root() function, please follow the way suggested by Mr. #paxdiablo.
For that data, your two roots are 5 and 3. With p == 2 and q == 4:
if (root1<=q || root1>=p)
becomes:
if (5<=4 || 5>=2)
which is true, so you'll get 5.
The if condition you want is:
if ((p <= root1) && (root1 <= q))
as shown in the following program, that produces the correct 3:
#include<stdio.h>
#include<math.h>
float find_root (float a, float b, float c, float p, float q) {
float d,root1,root2;
d = b * b - 4 * a * c;
root1 = ( -b + sqrt(d)) / (2* a);
root2 = ( -b - sqrt(d)) / (2* a);
if ((p <= root1) && (root1 <= q))
return root1;
return root2;
}
int main (void) {
printf ("%f\n", find_root(1, -8, 15, 2, 4));
return 0;
}
That's the logic errors with your calculations of the roots.
Just keep in mind there are other issues with your code.
You need to ensure you actually call the function itself, your main as it stands does not.
It also wont produce a value within the p/q bounds, instead it will give you the first root if it's within those bounds, otherwise it'll give you the second root regardless of its value.
You may want to catch the situation where d is negative, since you don't want to take the square root of it:
a = 1000, b = 0, c = 1000: d <- -4,000,000
And, lastly, if your compiler is complaining about not being able to link sqrt (as per one of your comments), you'll probably find you can fix that by specifying the math library, something like:
gcc -o myprog myprog.c -lm
Your program starts at main by definition.
Your main function is not calling find_root but it should.
You need to compile with all warnings & debug info (gcc -Wall -Wextra -g) then use a debugger (gdb) to run your code step by step to understand the behavior of your program, so compile with
gcc -Wall -Wextra -g yoursource.c -lm -o yourbinary
or with
clang -Wall -Wextra -g yoursource.c -lm -o yourbinary
then learn how to use gdb (e.g. run gdb ./yourbinary ... and later ./yourbinary without a debugger)
Then you'll think and improve the source code and recompile it, and debug it again. And repeat that process till you are happy with your program.
BTW, you'll better end your printf format strings with \n or learn about fflush(3)
Don't forget to read the documentation of every function (like printf(3) ...) that you are calling.
You might want to give some arguments (thru your main(int argc, char**argv) ...) to your program. You could use atof(3) to convert them to a double
Read also about undefined behavior, which you should always avoid.
BTW, you can use any standard C compiler (and editor like emacs or gedit) for your homework, e.g. use gcc or clang on your Linux laptop (then use gdb ...). You don't need a specific seashell
Change this condition
if (root1<=q || root1>=p)
to
if (root1<=q && root1>=p)
otherwise if anyone of the conditions is satisfied, root1 will be returned and root2 will almost never be returned. Hope this fixes your problem.

Why does this code keep giving this error? Syntax error: Bad for loop variable

This is copied from The C Programming Language By Ritchie. I've tried to make some modifications but it always gets stuck on the for loop (line 7)
#include <stdio.h>
main()
{
int fahr;
for(fahr = 0; fahr <= 300; fahr = fahr + 20)
{
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
}
error: ./farn.c: 8: ./farn.c: Syntax error: Bad for loop variable
I reproduced your problem. On Ubuntu, /bin/sh is symbolically linked to dash.
$ dash ./farn.c
./farn.c: 8: Syntax error: Bad for loop variable
It is very rare for a C program to be correctly interpreted by a Bourne shell interpreter (or one of its derivatives).
Compile the program with a C compiler, and run the executable (alternatively, use a C language interpreter if you can find one). On Ubuntu, you can use gcc:
$ gcc -W -Wall -Werror -pedantic -std=c99 farn.c -o farn
$ ./farn
Since the K&R book predates C.99, the above compilation command will generate an error:
cc1: warnings being treated as errors
farn.c:4: warning: return type defaults to 'int'
To fix this, you can simply update the declaration of main() with an explicit int return type. In C.99, encountering the } at the end of main() implicitly returns 0, so adding int is sufficient.
#include <stdio.h>
int main()
{
int fahr;
for(fahr = 0; fahr <= 300; fahr = fahr + 20)
{
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
}
Other than the fact that you're defining main() in a very lazy way and the lack of a return statement, I don't see anything wrong at all with the code above. After fixing those 2 issues, it compiled and ran just fine with the following options:
gcc temperature.c -g -Wall -Werror -pedantic -o temperature
As an aside, the entry-point to main should be either of:
int main(void) // You *can* leave void out here, but it's best to be explicit
int main(int argc, char* argv[]) // 2nd arg could also be char** argv
And you should always return an integer value from main, usually a return of 0 indicates the program ran successfully.
Your code compiles correctly. This is the proof : http://codepad.org/hryZ2dEm
I have also added the return type and the return instruction in the main function to make your code conform to the standard. Try to use the small changes I have inserted.
Let me know if you still have a problem.
Thank for the advice everyone. I solved my problem by using GCC like a boss.
gcc farn.c -o farn
then
./farn
works great. :-)

Resources