Should I Use Printf in My C++ Code

Should I use printf in my C++ code?

My students, who learn cin and cout first, then learn printf later, overwhelmingly prefer printf (or more usually fprintf). I myself have found the printf model sufficiently readable that I have ported it to other programming languages. So has Olivier Danvy, who has even made it type-safe.

Provided you have a compiler that is capable of type-checking calls to printf, I see no reason not to use fprintf and friends in C++.

Disclaimer: I am a terrible C++ programmer.

Need an explanation in which occasions we should use & with printf in C

To answer your question, let's review what the & operator does, and what types of values we need to pass to printf, and also, for comparison, what types of values we need to pass to scanf.

If you have a thing x, then the expression &x gives you a pointer to x. If x is an int, &x gives a pointer-to-int. If x is a char, &x gives pointer-to-char.

For example, if I write

int i;
int *ip;
ip = &i;

I have declared an int variable i, and a pointer-to-int variable ip. I have used the & operator to make a pointer to i, and I have stored that pointer-to-int in the variable ip. This is all fine.

As you may know, when you call scanf you always have to pass pointers to the variables which you want scanf to fill in for you. You can't write

scanf("%d %d", x, y);    /* WRONG */

because that would pass the values of the variables x and y to scanf. But you don't want to pass values to scanf, you want scanf to read some values from the user, and transmit them back to you. In fact, you want scanf to write to your variables x and y. That's why you pass pointers to x and y, so that scanf can use the pointers to fill in your variables. So that's why you almost always see &'s on the arguments in scanf calls.

But none of those reasons applies to printf. When you call printf, you do want to pass ordinary values to it. You're not (usually) asking printf to pass any data back to you. So most of the printf format specifiers are defined as accepting ordinary values, not pointers-to-values. So that's why you hardly ever see &'s in printf calls.

Now, you might think of & as an operator that "converts things" to pointers, but that's not really a good way of thinking about it. As I said, given an object x, the expression &x constructs a pointer to x. It doesn't "convert" anything; it certainly doesn't "convert" x. It constructs a brand-new pointer value, pointing to x.

In the code you posted, it looks like you might have used & in an attempt to perform such a "conversion". You had an array name of type array-of-array-of-char, or a two-dimensional array of characters. You were trying to print a string with %s. You knew, or perhaps your compiler warned you, that %s needs a pointer-to-char, and you knew (or your compiler told you) that the expression name[i][i] gave a value of type char. Now, putting a & in front of name[i][i] did indeed get a value of type pointer-to-char, as %s requires, and it might even have seemed to work, but it's a pretty haphazard solution.

It's true that printf's %s needs a pointer-to-char, but it doesn't need just any pointer-to-char; it needs a pointer-to-char that points to a valid, null-terminated string. And that's why, even though %s needs a pointer, you still don't usually see &'s in printf calls. You could use & on a single character variable to get a pointer to that character, like this:

char c = 'x';
printf("%s", &c); /* WRONG */

But this is broken code, and won't work properly, because the pointer you get is not to a valid string, because there's no null termination.

In your code, you probably want to change the line

printf("%s\t",&name[i][i]);

to

printf("%s\t",name[i]);

name is a two-dimensional array of char, but since a string in C is an array of char, you can also think of name as being a (single dimensional) array of strings, and I think that's how you're trying to use it.

Similarly, I suspect you want to change the line

scanf("%s",&name[rear][rear]);

to

scanf("%s", name[rear]);

But before you say "I thought scanf always needed &!", remember, the rule is that scanf needs a pointer. And since name[i] is an array, you automatically get a pointer to its first element when you pass it to scanf (or in fact when you use it in any expression). (And this is also the reasoning behind printf("%s\t",name[i]).)

If you wanted to use an explicit &, what you want is a pointer to the beginning of the string array you want scanf to fill in, so I think you'd want

scanf("%s", &name[rear][0]);

instead of the expression you had.

(It looks like you were, probably accidentally, running your strings down the diagonal of the name array, instead of down the left edge. It's also curious that you declared the perfectly square array

char name[max][max];

that is, 100 strings of 100 characters each. It's not wrong, and it'll work, but it's curious, and it makes it easier to mix up the rows and the columns.)

`

Why does my code only run when I use printf?

unsigned long total = (end - start) / CLOCKS_PER_SEC;
double ips = (max - min) / total;

When you add an additional printf, the code happens to run for long enough so that total is not zero.

Without the printf, your code is fast enough that it executes faster then a second, so (end - start) < CLOCKS_PER_SEC. Because of that (end - start) / CLOCKS_PER_SEC is zero, total is equal to zero and when dividing by zero your program gets terminated when receiving an SIGFPE signal (arithmetic exception).

This is a perfect case to brush up your debugger skills, such case is easily detectable with a debugger.

Syntax of printf in C

While it looks different in your editor, it's actually the same.

When you write

printf("Hello, World!\n");

in your editor, your compiler in principle change it to

char* hidden_unnamed_string = "Hello, World!\n";
printf(hidden_unnamed_string);

The string "Hello, World!\n" is called a string literal. The compiler will (automatically) place it somewhere in memory and then call printf with that memory address.

Here is an example from godbolt.org

Sample Image

On the left side you have the C program as it looks in your editor. To the right you have the compiled program.

Notice how the string is located outside the code block and labeled with LC0. Then inside the code block LC0 is loaded into edi (i.e. the address of/pointer to the string is loaded into edi) just before calling the printing function.

Also notice that the compiler decided to use puts instead of printf. Further notice that the string is stored without the \n. The reason is that puts unlike printf automatically adds a \n.

Should I use printf(\n) or putchar('\n') to print a newline in C?

It will make no difference which one you chose if you're using a modern compiler[1]. Take for example the following C code.

#include <stdlib.h>
#include <stdio.h>

void foo(void) {
putchar('\n');
}

void bar(void) {
printf("\n");
}

When compiled with gcc -O1 (optimizations enabled), we get the following (identical) machine code in both foo and bar:

movl    $10, %edi
popq %rbp
jmp _putchar ## TAILCALL

Both foo and bar end up calling putchar('\n'). In other words, modern C compilers are smart enough to optimize printf calls very efficiently. Just use whichever one you think is more clear and readable.


  1. I do not consider MS's cl to be a modern compiler.

Why do we use printf() function in C++?

I think some programmers find them easier or more accessible than the stream-based ones that are more common in C++.

Also, when doing complicated string formatting, the C way of using a formatting string can be perceived as being more concise and readable. I'm not arguing that it is, I'm just saying that in some cases some people might think it is, and thus chose to use printf().

How to use printf in C and what should my code be printing out?

It works perfectly well, no errors (except for the wrong quotes, i.e. “” instead of "" but I guess that's what your browser did).

Here's an example output of your code:

a) 22ff74
b) 22ff70
c) 20
d) 22ff6c
e) 5
f) 5

And here the explination

int x = 10;
int y = 20;

int *px = &x;
int *py = &y;

// You're printing out the pointer values here, which are the memory addresses of the
// variables x and y, respectively. Thus this may print any reasonable number within
// the stack memory space.
printf("a) %x\n", px);
printf("b) %x\n", py);

// Both pointer now point to y...
px = py;

// ... so this will print the value of y...
printf("c) %d\n", *px);

// ...and this will print the address of px, which will probably but not necessarily
// be the (memory address of y - 4) because the stack grows down and the compiler
// allocates space for the variables one after another (first y, then px).
printf("d) %x\n", &px);

x = 3;
y = 5;

// Remember that both px and px point to y? That's why both *px and *py resolve to
// the value of y = 5.
printf("e) %d\n", *px);
printf("f) %d\n", *py);

But anyway, for pointer you should usually use the "%p" format specifier instead of "%x" because that's for integers (which can be of different size than a pointer).



Related Topics



Leave a reply



Submit