I'm compiling the below C code with gcc. No errors are thrown during compilation or at runtime. I ran through the code with gdb, and the answer given in sum is correct at the end, yet the printf() does not display anything on the screen. I've tried all sorts of combinations of fprintf(), printf(), and fflush(), but nothing works.
What do I need to change so the program will print the result to stdout?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 9;
int i, sum; i = 1, sum = 0;
while (i < 2 * num) {
sum = sum + i * i;
++i;
}
printf("sum: %d\n", sum);
fflush(stdout);
return 0;
}
The code is correct, and should print sum: 1785 for any conforming implementation.
This is a guess (update: which turns out to be correct), but ...
You've named the source file test.c, and you compile it with:
$ gcc test.c -o test
(or something similar) and execute it with:
$ test
which produces no output.
The problem is that test is a standard Unix command (and also a built-in command in some shells). When you type a command name to the shell, it first looks for built-in commands, then for executables in directories specified in your $PATH environment variable.
To execute a command in the current directory, prepend ./ to the name:
$ ./test
sum: 1785
$
This applies to any command in the current directory. There are so many built-in commands that you can't reasonably avoid colliding with them. Cultivating the habit of running executables in the current directory by typing ./whatever means that name collisions don't matter.
(Don't be tempted to add . to the front of your $PATH; that's dangerous. Think about what could happen if you cd into a directory and type ls, if there happens to be a malicious ls command there.)
There is nothing wrong with your program. It has to work. Try running it with redirection:
./a.out > myout
..and see if you get any output. If not, I'd suspect there is a problem with some kind of standard library mismatch.
Another option to check would be to build using SUN C compiler as opposed to gcc and see if that works. If it does, gcc is the culprit.
Related
I need to get this stripped-down C program working on Windows 7 using MSys2's gcc toolchain:
#include <stdio.h>
void wmain(int argc, wchar_t *argv[])
{
for (int i = 1; i < argc; i++)
wprintf(L"%s\n", argv[i]);
}
The code compiles with
gcc -Wall -municode -O2 -march=x86-64 -m64 test.c
but gives me the following output
>> ./a.exe kk лл
k (!)
:?:?
I have the following questions:
What am I doing wrong?
How would I downgrade the compiler to
version, say, 9.x, or 10.1? (I'm under the impression that the very
same program compiled about one year ago used to work correctly)
Edit [1]: Meanwhile I managed to set up a new MSys2 environment using gcc 9.3. The "error" persists, so it's not the compiler.
Edit [2]: "Some programmer dude" (cmp. below) described the "immediate" solution (THX!).
Even for the wide-character wprintf the format %s is for narrow character strings.
You need to use %ls to print wide-character strings:
wprintf(L"%ls\n", argv[i]);
However this might still not be enough, as the actual encoding of the input (including arguments) might not be what's expected. You need to take into account the encoding used by the terminal the program is running in.
This is my program code:
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
void function() {
srand(time(NULL));
while(1) {
int n = rand();
printf("%d ", n);
//sleep(1);
}
}
int main() {
pid_t pid;
pid = fork();
if (pid == 0) {
function();
}
}
With the sleep line commented out (as in the code above) the program works fine (i.e. it prints a bunch of random numbers too fast to even see if they are actually random), but if I remove the comment the program doesn't print anything and exits (not even the first time, before it gets to the sleep), even though it compiles without warnings or errors with or without the comment.
but if I remove the comment the program doesn't print anything and exits
It does not print, but it does not really exit either. It will still be running a process in the background. And that process runs your infinite while loop.
Using your code in p.c:
$ gcc p.c
$ ./a.out
$ ps -A | grep a.out
267282 pts/0 00:00:00 a.out
$ killall a.out
$ killall a.out
a.out: no process found
The problem is that printf does not really print. It only sends data to the output buffer. In order to force the output buffer to be printed, invoke fflush(stdout)
If you're not flushing, then you just rely on the behavior of the terminal you're using. It's very common for terminals to flush when you write a newline character to the output stream. That's one reason why it's preferable to use printf("data\n") instead of printf("\ndata"). See this question for more info: https://softwareengineering.stackexchange.com/q/381711/283695
I'd suspect that if you just leave your program running, it will eventually print. It makes sense that it has a finite buffer and that it flushes when it gets full. But that's just an (educated) guess, and it depends on your terminal.
it prints a bunch of random numbers too fast to even see if they are actually random
How do you see if a sequence of numbers is random? (Playing the devils advocate)
I believe you need to call fflush(3) from time to time. See also setvbuf(3) and stdio(3) and sysconf(3).
I guess that if you coded:
while(1) {
int n = rand();
printf("%d ", n);
if (n % 4 == 0)
fflush(NULL);
sleep(1);
}
The behavior of your program might be more user friendly. The buffer of stdout might have several dozens of kilobytes at least.
BTW, I could be wrong. Check by reading a recent C draft standard (perhaps n2176).
At the very least, see this C reference website then syscalls(2), fork(2) and sleep(3).
You need to call waitpid(2) or a similar function for every successful fork(2).
If on Linux, read also Advanced Linux Programming and use both strace(1) and gdb(1) to understand the behavior of your program. With GCC don't forget to compile it as gcc -Wall -Wextra -g to get all warnings and debug info.
Consider also using the Clang static analyzer.
We have started C programming in my Uni, and I appear to have fallen at the first hurdle. My very simple program will not print to the terminal. The code:
#include "stdio.h"
int main(){
printf("Memory size for type %s = %lu \n", "double", sizeof(double));
return 0;
}
I have used all my google-fu, and have only found that I apparently should use vprint, but it won't take three arguments, only two. Also, bizarrely, printing to a file works! See screenshot:
Terminal screenshot
The format specifier for size_t(the return type of sizeof) is %zu.
printf("Memory size for type %s = %zu \n", "double", sizeof(double));
Alright, apparently, when I simply run the program, Clang prints the output to a.out in the same directory as the code, and there's nothing I can do about it. Whatever, as long as the code works - means I can turn it in, and I'll be checking my work with ./a.out.
According to your screenshot, it appears that there is a misconception here :
gcc 1.c
gcc is used to compile the program (creating the executable, here using the source file 1.c), not to run it. The program might have been compiled under the name 'a.out'.
When you compile your program using :
gcc 1.c -o 1.txt
You are actually compiling the program with gcc and, using the option -o, creating the executable under the name 1.txt (a program can be named whatever you want, or almost)
Then when you type
./1.txt
you are actually running the program (1.txt) and you have the expected output.
I am using Vim as my editor and GCC as my compiler, but it’s not working quite right. Let‘s say I am making a basic program to determine if a number is odd or even. Here is my code:
#include <stdio.h>
int main(int argc, char argv[])
{
int i;
printf("Enter a number: ");
scanf("%d\n", &i);
printf("%d\n", i);
if(i % 2 == 0)
{
printf("Your number is even.\n");
}
else if(i % 2 != 0)
{
printf("Your number is odd.\n");
}
else
{
printf("Invalid input.\n");
}
getchar();
return 0;
}
I'm not sure if I am programming this wrong, or gcc is just not a good compiler, or whatever. I am running linux, which I dual boot with windows. Now I press ctrl-d to stop the process, and only then does it print me back my number, and tell if it is odd or even. It isn't just this one, a lot of other programs with similar formats seem to do this to.
~ $ ./test
Enter a number: 45
45 //I press enter, nothing happends. Ctrl-d
Your number is even. //ctrl-d again
~ $
So what I'm asking is, is there a way to program it so that I don't have to quit the program in order for it to work, or is there another compiler that wouldn't have this problem? I am running on Ubuntu 14.04 dual booted with Windows 8.1.
\n in the format for scanf means "read until hit into non-whitespace character and then ignore them". Remove it and make the format for reading "%d".
to get gcc to work from vim,
goto the vim command prompt
shell gcc <and all needed parameters>
Or open another command window
set it to the same directory as the program being edited
gcc <and all needed parameters>
in general, try to make the compile step separate from the link step. I.E. to compile:
gcc -c <mySource.c> -Wall -Wextra -pedantic -std=c99 -o mySource.o
if any header files, other than those in the default 'include' path then add
-I<pathToHeaderFile>
which is often in the same directory so would be:
-I.
then link with:
gcc mySource.o -o mySource
You can add the -ggdb parameter to both lines if you plan on doing any debugging.
to add any library directories then on the link step append
-L<pathToLibrary>
to add any libraries then on the link step append, after any library parameters:
-l<shortLibName>
The initialization file for vim can contain the necessary info to invoke gcc by some keystroke combination, but I'm not totally familiar with the details.
I have two (Ubuntu Linux) bash scripts which take input arguments. They need to be run simultaneously. I tried execve with arguments e.g.
char *argv[10] = { "/mnt/hgfs/F/working/script.sh", "file1", "file2", NULL };
execve(argv[0], argv, NULL)
but the bash script can't seem to find any arguments at e.g. $0, $1, $2.
printf "gcc -c ./%s.c -o ./%s.o\n" $1 $1;
gcc -c ./$1.c -o ./$1.o -g
exit 0;
output is gcc -c ./main.c -o ./main.o
and then a lot of errors like /usr/include/libio.h:53:21: error: stdarg.h: No such file or directory
What's missing?
Does your script start with the hashbang line? I think that's a must, something like:
#!/bin/bash
For example, see the following C program:
#include <stdio.h>
#include <unistd.h>
char *argv[10] = { "./qq.sh", "file1", NULL };
int main (void) {
int rc = execve (argv[0], argv, NULL);
printf ("rc = %d\n", rc);
return 0;
}
When this is compiled and run with the following qq.sh file, it outputs rc = -1:
echo $1
when you change the file to:
#!/bin/bash
echo $1
it outputs:
file1
as expected.
The other thing you need to watch out for is with using these VMWare shared folders, evidenced by /mnt/hgfs. If the file was created with a Windows-type editor, it may have the "DOS" line endings of carriage-return/line-feed - that may well be causing problems with the execution of the scripts.
You can check for this by running:
od -xcb /mnt/hgfs/F/working/script.sh
and seeing if any \r characters appear.
For example, if I use the shell script with the hashbang line in it (but appen a carriage return to the line), I also get the rc = -1 output, meaning it couldn't find the shell.
And, now, based on your edits, your script has no trouble interpreting the arguments at all. The fact that it outputs:
gcc -c ./main.c -o ./main.o
is proof positive of this since it's seeing $1 as main.
The problem you actually have is that the compiler is working but it cannot find strdarg.h included from your libio.h file - this has nothing to do with whether bash can see those arguments.
My suggestion is to try and compile it manually with that command and see if you get the same errors. If so, it's a problem with what you're trying to compile rather than a bash or exec issue.
If it does compile okay, it may be because of the destruction of the environment variables in your execve call.