I can't get the argument index format specifier on fprintf() to work when compiling C code on Windows with gcc-7.2.0-mingw.
Take the following program as an example:
#include <stdio.h>
int main(void) {
int x;
x = 10;
fprintf(stdout, "%1$d == %1$d\n", x);
return 0;
}
Let's compile and run it:
C:\path\to\dir>gcc -Wall -std=c89 -o main.exe main.c
C:\path\to\dir>main.exe
$d == $d
C:\path\to\dir>
While I expected the output to be 10 == 10 (Try it online!).
What's happening and how can I make the argument index specifier work properly?
Note: the same happens if I try to print strings, floats or anything else.
Related
Consider the following code:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("main\n");
int a;
scanf("%d", &a);
printf("a = %d\n", a);
return 0;
}
int main1() {
printf("main1\n");
int a;
scanf("%d", &a);
printf("a = %d\n", a);
exit(0);
return 0;
}
int main2() {
printf("main2\n");
int a = getchar() - '0';
int b = getchar() - '0';
int c = getchar() - '0';
printf("a = %d\n", 100 * a + 10 * b + c);
exit(0);
return 0;
}
Assuming that the code resides in a file called test.c, the following works fine (it prints "a = 123"):
gcc -o test test.c
echo 123 | ./test
If, however, I run the program with a custom entry point, I get the dreaded Segmentation fault:
gcc -o test test.c -e"main1"
echo 123 | ./test
But if I replace the scanf with three getchars, the program runs fine again despite being run with a custom entry point:
gcc -o test test.c -e"main2"
echo 123 | ./test
To make things even more interesting, these problems occur with gcc 7.4.0 but not with gcc 4.8.4.
Any ideas?
The -e command line flag redefines the actual entry point of your program, not the “user” entry point. By default, using GCC with the GNU C standard library (glibc) this entry point is called _start, and it performs further setup before invoking the user-provided main function.
If you want to replace this entry point and continue using glibc you’ll need to perform further setup yourself. But alternatively you can use the following method to replace the main entry point, which is much simpler:
gcc -c test.c
objcopy --redefine-sym main1=main test.o
gcc -o test test.o
Note, this will only work if you don’t define main in your code, otherwise you’ll get a “multiple definition of `main'” error from the linker.
Is it possible to write a script to run this code for different values of A;
#include <stdio.h>
#define A 3
int main (){
printf("In this version A = %d\n", A);
return(0);
}
I guess something like for loop?
Is it possible to write a script to run this code for different values of A;
Not as it is because the macro A has a fixed value defined in your code. Instead you can pass the value as an argument:
#include <stdio.h>
int main(int argc, char **argv){
if(argc == 2) {
printf("In this version A = %s\n", argv[1]);
}
return 0;
}
(The code doesn't check if its input is an integer -- which you can test if necessary).
and you can run it via script. For example, compile the above (gcc -Wall -Wextra test.c -o test) using a for loop of bash:
$ for ((i = 0; i < 10; i++)); do ./test $i; done
In this version A = 0
In this version A = 1
In this version A = 2
In this version A = 3
In this version A = 4
In this version A = 5
In this version A = 6
In this version A = 7
In this version A = 8
In this version A = 9
$
No. But you can make A a command line arg:
#include <stdio.h>
int main (int argc, char *argv[]) {
int a;
if (argc != 2 || sscanf(argv[1], "%d", &a) != 1) return 1;
printf("In this version A = %d\n", a);
return 0;
}
Compile to a binary named foo, then
foo 42
will print
In this version A = 42
You can also compile different versions by defining A in the compilation command line. From your original program, remove the #define. Then
gcc -DA=42 foo.c -o foo
./foo
will print the same as above.
DO you need run program repeated from script? why not to make program that accepts arguments from command line?
1)The main() function actually takes arguments, you can compile program once and pass different parameters, as shown in answers above
2) If you need to change some code parameters from make script, I'd say, create separate header that would contain defines and write script that would echo into that file (> for start, >> to continue writing).
3) Alternative way you can call you compiler with flag that would be equal to #define macro-command. For gcc it's -D, for example -DA=3 instead of #define A 3.
Most programs use makefile to be compiled. For that case you can script make file to use 2) or 3) Former is preferable because you do not need to pass that argument to all compilation targets, reducing time or re-compiling. There are tools for more advanced manipulations, like autoconf.
I was trying today to check an Answer and I realized that if i use codeblocks (with gcc) i have to treat the error different from the command line (Ubuntu Linux) using gcc.
The program is like this:
#include<stdio.h>
#include<math.h>
int main(void){
double len,x,y =0;
int n=123456;
len=floor(log10(abs(n))) + 1;
x = n / pow(10, len / 2);
y = n - x * pow(10, len / 2);
printf("First Half = %f",x);
printf("\nSecond Half = %f",y);
return 0;
}
And if i try to compile it i get:
error: implicit declaration of function ‘abs’ [-Werror=implicit-function-declaration]|
So here is the funny thing. I added -lm to the Compiler => global compiler => settings => Other settings, but the result is the same.
It is working only if i include stdlib.h.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void){
double len,x,y =0;
int n=123456;
len=floor(log10(abs(n))) + 1;
x = n / pow(10, len / 2);
y = n - x * pow(10, len / 2);
printf("First Half = %f",x);
printf("\nSecond Half = %f",y);
return 0;
}
But if I use command line (in terminal) using the comand:
gcc program.c -o program -lm
The program compiled successfully.
My question: Why happens this ?
I did a research on interent and found that some people says the abs function is declared in stdlib.h, not math.h. but if i compile in command line (without including stdlib.h) with -lm works. I'm confused.
Short answer: Try
gcc -Wall -Wextra -pedantic -o program -lm
or
gcc -Wall -Wextra -Werror -pedantic -o program -lm
to make it fail on warnings as Codeblocks seems to do.
Long answer: Linking to a library is a completely different matter than including a header file. In C, for historic reasons, it is "allowed" to use a function that is not declared. The compiler in this case assumes a function returning int and taking whatever arguments you give it. For abs(), these assumptions hold. So later, the linker finds the function when linking with libm and everything is fine.
But there are quite some catches: First you will miss simple typos if you don't enable warnings. Second, the compiler is unable to check the arguments you give -> crashing program ahead. And even more problems are to expect if the function does return something other than int.
abs() is declared in stdlib.h. To use it, include this header. And always enable compiler warnings (Codeblocks obviously does it for you).
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. :-)
The source code of square.c is:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int square(int *ptr)
{
int a;
a = *ptr;
return a * a;
}
int main(int argc, char **argv)
{
int a, aa;
srandom(time(NULL));
a = random() % 10 + 1;
aa = square(&a);
printf("%d\n", aa);
return 0;
}
The command-line to compile the source code is:
gcc square.c -o square
Is it possible to run the square executable in Linux so that the printed value will not be a square of any integer number?
Any method of running the program is allowed.
Yes. We can override printf.
Write the code in your post into square.c and compile it with gcc square.c
Make this file, fakesquare.c
int printf(char *str,int i)
{
return puts("7");
}
Compile fakesquare.c as a shared library:
gcc -fPIC -o libfakesquare.so -shared fakesquare.c
Run the square program with libfakesquare.so preloaded:
[15:27:27 0 /tmp] $ LD_PRELOAD=./libfakesqare.so ./a.out
7
[15:29:16 0 /tmp] $ LD_PRELOAD=./libfakesqare.so ./a.out
7
[15:29:16 0 /tmp] $ LD_PRELOAD=./libfakesqare.so ./a.out
7
Witout libfakeshared.so preloaded:
[15:29:40 0 /tmp] $ ./a.out
36
[15:29:41 0 /tmp] $ ./a.out
16
[15:29:42 0 /tmp] $ ./a.out
64
You could use this :
Fastest way to determine if an integer's square root is an integer
Their code seems optimized, but whichever is simplest should do the trick for you.
The only dependency at your code is libc. If libc stays unmodified then your code will always work.
Also your program will fail if before running it, all available memory is exhausted. You can always check if ptr!=NULL.
Assuming a standard C environment I don't see a reason why this should fail on a standard platform. The code might fail if printf is not doing what it is inteded to do, but probably this is not what you are asking for. It also might fail on a platform where int is as small as a byte and a byte is only 6 bits wide. In this case your square function might calculate 9*9=81 which will not fit in the result type int (0..63 for 6 bit-byte). But in my opinion this is a quite academic case.