Two possibilities to print a string with printf - c

Task: Write two possibilities printf commands to print the following char array.
char str[] = "Im a sentence";
I found out one:
printf("%s", str) // this prints: Im a sentence
But i need another one, can anyone help me?

It's a silly question, but they are probably looking for this:
printf(str); // 1
printf("%s", str); // 2
Note that (1) is not considered good practice, but it is valid and it works.

The other one would be passing the string directly to printf:
printf(str);
As long as str is free of format specifiers, this is going to work. However, you should avoid using this in production code, because the compiler would be unable to properly diagnose potential mismatches between parameter types and format specifiers, which could lead to undefined behavior.

int x;
for (x=0;x<strlen(str);++x)
printf("%c",str[x]);

Related

Why do I need an ampersand for this printf statement?

Why do I need an ampersand before the array in the printf statement here, but any other time ampersand is only used in scanf?
Completely new so if you could explain as simply as possible that would help.
int main(void) {
char word[1];
scanf("%s", &word[0]);
printf("%s", word[0]);
return 0;
}
You do need one. It's incorrect without one and leads to undefined behavior, which may cause anything to happen (even the program appearing to work correctly). Also, word[1] can only hold the null terminator of an empty string, any more than that and it will cause the buffer to overflow, also causing undefined behavior. It should be:
int main(void) {
char word[10]; // or any value that is big enough for the input that your anticipating
scanf("%9s", &word[0]);
printf("%s", &word[0]);
return 0;
}
And of course you can replace &word[0] with word.
Also note that I put %9s instead of just %s for the scanf call, which means that it will get at most 9 characters, which with the added null terminator fits into the word[10] that we have as an example. This way you don't get undefined behavior if the user enters something that's too big and instead it would just truncate that input.
word[0] is the first character.
the & sign is used to get a pointer to such character.
scanf("%s", &word[0]);
printf("%s", word[0]);
In C, a string (addressed by %s in above statements) is defined as an array. Your declaration of "word":
char word[1];
declares an array, so that array can be a string (I wrote can, because it's a very short string...). If you use the identifier alone, "word", the compiler uses a pointer to the first element of the array. Hence:
scanf("%s", word);
printf("%s", word);
are both correct. But if you use an index into the array, like "word[0]", then you are no more using the array per se, but instead an element of it. This notation does not generate a pointer, but your above statements do need a pointer. So you can use an "&" to get a pointer.
Conclusion: if you have a string, use its simple name without indexing inside the array. Using the ampersand makes it clear that we pass a reference, but "&word[0]" is ugly and, moreover, everybody should know that scanf() writes into its arguments.

print text via pointer

i am learning now c and i come up with this example, where i can print a text using pointers.
#include <stdio.h>
main ()
{
char *quotes = "One good thing about music, when it hits you, you feel no pain. \"Bob Marley\"\n";
printf(quotes);
}
I get a warning from the compiler "format not a string literal and no format arguments" and when I execute the program it runs successfully.I read some other questions here that they had the same warning from the compiler but I didn't find an answer that fits me. I understood the reason why i get this message:
This warning is gcc's way of telling you that it cannot verify the format string argument to the printf style function (printf, fprintf... etc). This warning is generated when the compiler can't manually peek into the string and ensure that everything will go as you intend during runtime...
Case 3. Now this is somewhat your case. You are taking a string generated at runtime and trying to print it. The warning you are getting is the compiler warning you that there could be a format specifier in the string. Say for eg "bad%sdata". In this case, the runtime will try to access a non-existent argument to match the %s. Even worse, this could be a user trying to exploit your program (causing it to read data that is not safe to read).
(See the answer)
but what i have to add in my case to in order to have not warnings from the compiler?
Change it to printf("%s", quotes); which adds the specifier that quotes is a 'string', or array of char.
You need to tell printf what is it that you are printing. %s descriptor will tell printf that you are printing a string.
Format of printf = ("descriptor of what type of data you are printing",variable holding the data);
descriptor for strings is %s, for characters %c, for int %d
Change printf to:
printf("%s",quotes);
You have to specify format string - in simplest form:
char *quotes = "One good thing about music(...)\n";
printf("%s", quotes);
or, you can use format string to decorate output:
char *quotes = "One good thing about music(...)"; // no newline
printf("%s\n", quotes); // newline added here
or, if you don't want to mess with format strings:
char *quotes = "One good thing about music(...)"; // no newline
puts(quotes); // puts() adds newline
or
char *quotes = "One good thing about music(...)\n";
fputs(quotes,stdout);
This warning is gcc's way of telling you that it cannot verify the format string argument to the printf style function (printf, fprintf... etc). This warning is generated when the compiler can't manually peek into the string and ensure that everything will go as you intend during runtime. Lets look at a couple of examples.
So as other suggested explicitly use format specifier to tell the compiler...i.e.
printf("%s",quotes);
You are getting the warning because it is dangerous when the string you are printing contains '%'. In this line it makes no sense for percents but when you want to print this for instance:
int main ()
{
int percent = 10;
char *s = "%discount: %d\n";
printf(s, percent);
return 0;
}
your program will likely crash when printf encounters the second percent and it tries to pop a value from the stack from printf.
When you want to print a percent sign use: "%%discount:"
Try this:
#include <stdio.h>
main ()
{
char *quotes = "One good thing about music, when it hits you, you feel no pain. \"Bob Marley\"\n";
puts(quotes); //Either
printf("%s",quotes);//or
return 0;
}

XCode saying something is potentially insecure for a C program? What exactly does it mean?

Say we are working in C.
if I go ahead and do this:
char *word;
word = "Hello friends";
printf(word);
then XCode tells me that because I'm not using a string literal, that I might have something that is potentially insecure. Does that mean an opening for something to hack my program? If so, how could that happen?
Alternatively, if I do this:
char *word;
word = "Hello friends";
printf("%s", word);
Then XCode raises no flags and I'm fine. What exactly is the difference?
The first argument to printf is not the string you want to print. It's a format string. It can contain formatting instructions which results in the string that is printed once it is combined with further arguments.
Your first example is an uncontrolled format string vulnerability.
The issue is that in the first case if word contains formatting specs (%d, %f, %s, etc.) then printf() will assume those values are on the stack, but in fact they aren't, which could lead to a crash.
Use puts() or fputs() instead if you don't care about formatting.

Secure handling of string variables

Hello I'm quite new to C and in a nutshell I was doing the following as part of my assignment in class:
foo (char *var) {
printf(var);
}
I was told that this is bad practice and insecure but did not get much detailed information on this by my tutor. I assume that if the string value of var is controllable by the user it may be used to perform a bufferoverflow? How would I properly harden this code? Do I have to limit the str length or something?
Cheers & Thanks!
You should use:
printf("%s", var);
instead. The way you have it, I could enter %s as my input, and printf would read a random piece of memory as it looked for a string to print. That can cause any amount of unexpected behaviour.
This is UNSAFE because it could lead to a Format String Attack
Well, the first argument of printf is a format string. So the caller of your function could pass:
foo("%d")
and then printf would look for an integer which isn't there, and cause undefined behaviour. One possible fix would be for your function to call:
printf("%s", var);
which would have printf interpret var as a regular string (rather than a format).
Printf has the following signature:
int printf(
const char *format [,
argument]...
);
If the user inputs format characters for example %s all kinds of bad things will happen.
Use puts if you just want to output the string.

how can I printf in c

How can I make this print properly without using two printf calls?
char* second = "Second%d";
printf("First%d"second,1,2);
The code you showed us is syntactically invalid, but I presume you want to do something that has the same effect as:
printf("First%dSecond%d", 1, 2);
As you know, the first argument to printf is the format string. It doesn't have to be a literal; you can build it any way you like.
Here's an example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *second = "Second%d";
char format[100];
strcpy(format, "First%d");
strcat(format, second);
printf(format, 1, 2);
putchar('\n');
return 0;
}
Some notes:
I've added a newline after the output. Output text should (almost) always be terminated by a newline.
I've set an arbitrary size of 100 bytes for the format string. More generally, you could declare
char *format;
and initialize it with a call to malloc(), allocating the size you actually need (and checking that malloc() didn't signal failure by returning a null pointer); you'd then want to call free(format); after you're done with it.
As templatetypedef says in a comment, this kind of thing can be potentially dangerous if the format string comes from an uncontrolled source.
(Or you could just call printf twice; it's not that much more expensive than calling it once.)
Use the preprocessor to concatenate the two strings.
#define second "Second%d"
printf("First%d"second,1,2);
Do not do this in a real program.
char *second = "Second %d";
char *first = "First %d";
char largebuffer[256];
strcpy (largebuffer, first);
strcat (largebuffer, second);
printf (largebuffer, 1, 2);
The problem with using generated formats such as the method above is that the printf() function, since it is a variable length argument list, has no way of knowing the number of arguments provided. What it does is to use the format string provided and using the types as described in the format string it will then pick that number and types of arguments from the argument list.
If you provide the correct number of arguments like in the example above in which there are two %d formats and there are two integers provided to be printed in those places, everything is fine. However what if you do something like the following:
char *second = "Second %s";
char *first = "First %d";
char largebuffer[256];
strcpy (largebuffer, first);
strcat (largebuffer, second);
printf (largebuffer, 1);
In this example the printf() function is expecting the format string as well as a variable number of arguments. The format string says that there will be two additional arguments, an integer and a zero terminated character string. However only one additional argument is provided so the printf() function will just use what ever is next on the stack as being a pointer to a zero terminated character string.
If you are lucky, the data that the printf() function interprets as a pointer will a valid memory address for your application and the memory area pointed to will be a couple of characters terminated by a zero. If you are less lucky the pointer will be zero or garbage and you will get an access violation right then and it will be easy to find the cause of the application crash. If you have no luck at all, the pointer will be good enough that it will point to a valid address that is about 2K of characters and the result is that printf() will totally mess up your stack and go into the weeds and the resulting crash data will be pretty useless.
char *second = "Second%d";
char tmp[256];
memset(tmp, 0, 256);
sprintf(tmp, second, 2);
printf("First%d%s", 1,tmp);
Or something like that
I'm assuming you want the output:
First 1 Second 2
To do this we need to understand printf's functionality a little better. The real reason that printf is so useful is that it not only prints strings, but also formats variables for you. Depending on how you want your variable formatted you need to use different formatting characters. %d tells printf to format the variable as a signed integer, which you already know. However, there are other formats, such as %f for floats and doubles, %l% for long integers, and %s for strings, or char*.
Using the %s formatting character to print your char* variable, second, our code looks like this:
char* second = "Second";
printf ( " First %d %s %d ", 1, second, 2 );
This tells printf that you want the first variable formatted as an integer, the second as a string, and the third as another integer.

Resources