Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #72699 > unrolled thread
| Started by | MehdiAmini <atorrses@gmail.com> |
|---|---|
| First post | 2015-10-13 14:09 +0000 |
| Last post | 2015-10-25 23:02 +0100 |
| Articles | 13 — 9 participants |
Back to article view | Back to comp.lang.c
A printf question. MehdiAmini <atorrses@gmail.com> - 2015-10-13 14:09 +0000
Re: A printf question. Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-10-13 10:46 -0400
Re: A printf question. Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-13 09:19 -0700
Re: A printf question. Keith Thompson <kst-u@mib.org> - 2015-10-13 10:45 -0700
Re: A printf question. David Brown <david.brown@hesbynett.no> - 2015-10-13 23:15 +0200
Re: A printf question. James Kuyper <jameskuyper@verizon.net> - 2015-10-13 15:25 -0400
Re: A printf question. glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-10-14 02:55 +0000
Re: A printf question. James Kuyper <jameskuyper@verizon.net> - 2015-10-13 23:12 -0400
Re: A printf question. supercat@casperkitty.com - 2015-10-14 06:34 -0700
Re: A printf question. Keith Thompson <kst-u@mib.org> - 2015-10-14 10:26 -0700
Re: A printf question. MehdiAmini <atorrses@gmail.com> - 2015-10-15 14:06 +0000
Re: A printf question. James Kuyper <jameskuyper@verizon.net> - 2015-10-15 10:26 -0400
Re: A printf question. Noob <root@127.0.0.1> - 2015-10-25 23:02 +0100
| From | MehdiAmini <atorrses@gmail.com> |
|---|---|
| Date | 2015-10-13 14:09 +0000 |
| Subject | A printf question. |
| Message-ID | <mvj3b8$i7h$1@dont-email.me> |
// Following a discussion on a forum, I got this code snippet:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char * const message="My str\n";
//printf("%s", message); // This seems to be correct.
printf(message); // Should not this produce a diagnostic?
return EXIT_SUCCESS;
}
// MSVC++ and GCC online compilers do not produce any warning/error.
// MSVC++: Compiled with /EHsc /nologo /W4
// GCC: C++14 -Wall -Wextra -Wpedantic -O3
--
--------------------------------- --- -- -
Posted with NewsLeecher v7.0 Beta 7
Web @ http://www.newsleecher.com/?usenet
------------------- ----- ---- -- -
[toc] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2015-10-13 10:46 -0400 |
| Message-ID | <mvj5co$rs5$1@dont-email.me> |
| In reply to | #72699 |
On 10/13/2015 10:09 AM, MehdiAmini wrote:
> // Following a discussion on a forum, I got this code snippet:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
> const char * const message="My str\n";
>
> //printf("%s", message); // This seems to be correct.
> printf(message); // Should not this produce a diagnostic?
No diagnostic is required. The first argument to printf()
is a pointer to a format string, but it doesn't need to point
at a literal string constant: It can be a pointer to any kind
of string. If the string contains format directives they
tell printf() how to convert the additional arguments (which
must be of appropriate types), but if there are no directives
there are no conversions.
In your first (commented-out) printf() call, you have a
literal format string with one "%s" directive, and you have a
second string pointer argument to match the "%s". All is well.
In your second printf() call, you have one format string
pointer, this time not written as a literal. That's fine: It's
still a string pointer, so the compiler sees that it's the right
type for printf()'s first argument. The string itself has no
directives, so all its characters are simply copied to the ouput;
no additional arguments are needed.
If things are still unclear to you, please post again -- and
this time, explain exactly why you think a diagnostic should be
required (or desirable).
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-10-13 09:19 -0700 |
| Message-ID | <a86c606e-3da8-4561-9b40-2d5d8887fc3c@googlegroups.com> |
| In reply to | #72699 |
On Tuesday, October 13, 2015 at 3:12:07 PM UTC+1, Mehdi Amini Valashani son of Bahram wrote:
> // Following a discussion on a forum, I got this code snippet:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
> const char * const message="My str\n";
>
> //printf("%s", message); // This seems to be correct.
> printf(message); // Should not this produce a diagnostic?
>
> return EXIT_SUCCESS;
> }
>
No, its normally a bad idea to pass a string composed on the fly as the format argument
to printf (largely because you might have embedded percent signs in it), but it's
not prohibited, and occasionally it's the right thing to do.
printf("%s", message) is the normal way of printing out a string whose contents
aren't known at the point of making the call, however.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-10-13 10:45 -0700 |
| Message-ID | <ln37xebr27.fsf@kst-u.example.com> |
| In reply to | #72714 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> On Tuesday, October 13, 2015 at 3:12:07 PM UTC+1, Mehdi Amini Valashani son of Bahram wrote:
>> // Following a discussion on a forum, I got this code snippet:
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> int main(void)
>> {
>> const char * const message="My str\n";
>>
>> //printf("%s", message); // This seems to be correct.
>> printf(message); // Should not this produce a diagnostic?
>>
>> return EXIT_SUCCESS;
>> }
>>
> No, its normally a bad idea to pass a string composed on the fly as
> the format argument to printf (largely because you might have embedded
> percent signs in it), but it's not prohibited, and occasionally it's
> the right thing to do. printf("%s", message) is the normal way of
> printing out a string whose contents aren't known at the point of
> making the call, however.
Either that or fputs(message, stdout), or puts(message) if you want to
add a newline.
printf format strings are typically literals, which are safe *if* the
code is written carefully and correctly. A format string can be
generated at run time by some other means, but you *must* be careful not
to include '%' characters that you didn't intend to. Using unchecked
user input as a format string is arbitrarily dangerous.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-10-13 23:15 +0200 |
| Message-ID | <mvjs6j$3f6$1@dont-email.me> |
| In reply to | #72727 |
On 13/10/15 19:45, Keith Thompson wrote:
> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>> On Tuesday, October 13, 2015 at 3:12:07 PM UTC+1, Mehdi Amini Valashani son of Bahram wrote:
>>> // Following a discussion on a forum, I got this code snippet:
>>>
>>> #include <stdio.h>
>>> #include <stdlib.h>
>>>
>>> int main(void)
>>> {
>>> const char * const message="My str\n";
>>>
>>> //printf("%s", message); // This seems to be correct.
>>> printf(message); // Should not this produce a diagnostic?
>>>
>>> return EXIT_SUCCESS;
>>> }
>>>
>> No, its normally a bad idea to pass a string composed on the fly as
>> the format argument to printf (largely because you might have embedded
>> percent signs in it), but it's not prohibited, and occasionally it's
>> the right thing to do. printf("%s", message) is the normal way of
>> printing out a string whose contents aren't known at the point of
>> making the call, however.
>
> Either that or fputs(message, stdout), or puts(message) if you want to
> add a newline.
>
> printf format strings are typically literals, which are safe *if* the
> code is written carefully and correctly. A format string can be
> generated at run time by some other means, but you *must* be careful not
> to include '%' characters that you didn't intend to. Using unchecked
> user input as a format string is arbitrarily dangerous.
>
Using a literal string for printf also means that your compiler may be
able to do extra checking, to ensure that % characters in the format
match up with other arguments passed to printf. (gcc can certainly do
that, given the write options. And it translates "printf("%s",
message);" into a puts() call - removing the extra "\n". Write your
code in the clearest and safest manner, and let the compiler generate
the most efficient object code.)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-10-13 15:25 -0400 |
| Message-ID | <mvjlns$6ih$1@dont-email.me> |
| In reply to | #72699 |
On 10/13/2015 10:09 AM, MehdiAmini wrote:
> // Following a discussion on a forum, I got this code snippet:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
> const char * const message="My str\n";
>
> //printf("%s", message); // This seems to be correct.
> printf(message); // Should not this produce a diagnostic?
It would help us figure out what it is that you don't understand, if you
explain why you think a diagnostic should be produced.
> return EXIT_SUCCESS;
> }
<stdio.h> brings in a prototype declaration of printf() like the following:
int printf(const char * restrict format, ...); (7.21.6.3p1)
Such a prototype requires that:
1. The function be called with at least one argument.
printf(message) meets that requirement
2. The type of that argument must be convertible to "const char*".
The type of message is "const char*", and therefore trivially convertible.
There's several other possible issues that could render the behavior
undefined, but none of them apply, and even if they did, no diagnostic
would be required. The standard describes the format string as "composed
of zero or more directives: ordinary multi-byte characters (not %),
which are copied unchanged to the output stream, and conversion
specifications, ...". (7.21.6.1p3).
"message" points at "My str\n", which doesn't contain any conversion
specifiers, but there's no required minimum number of conversion
specifiers. It contains 8 ordinary multi-byte characters, which are
simply passed through.
--
James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2015-10-14 02:55 +0000 |
| Message-ID | <mvkg7v$v5d$1@speranza.aioe.org> |
| In reply to | #72735 |
James Kuyper <jameskuyper@verizon.net> wrote: (snip on printf with one argument) > <stdio.h> brings in a prototype declaration of printf() like the following: > int printf(const char * restrict format, ...); (7.21.6.3p1) > Such a prototype requires that: > 1. The function be called with at least one argument. > printf(message) meets that requirement > 2. The type of that argument must be convertible to "const char*". > The type of message is "const char*", and therefore trivially convertible. With compilers generating more and more warnings, possibly for things that are actually correct, I would not be surprised to see a warning for a single non-constant argument. -- glen
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-10-13 23:12 -0400 |
| Message-ID | <mvkh2q$58k$1@dont-email.me> |
| In reply to | #72783 |
On 10/13/2015 10:55 PM, glen herrmannsfeldt wrote: > James Kuyper <jameskuyper@verizon.net> wrote: > > (snip on printf with one argument) > >> <stdio.h> brings in a prototype declaration of printf() like the following: > >> int printf(const char * restrict format, ...); (7.21.6.3p1) > >> Such a prototype requires that: >> 1. The function be called with at least one argument. >> printf(message) meets that requirement >> 2. The type of that argument must be convertible to "const char*". >> The type of message is "const char*", and therefore trivially convertible. > > With compilers generating more and more warnings, possibly for things > that are actually correct, I would not be surprised to see a warning > for a single non-constant argument. True - but diagnostics are always permitted. The OP seems to be be concerned about whether a diagnostic is mandatory for this code. It's not clear whether he's asking why this particular compiler fails to generate the diagnostic that he thought was mandatory, or whether he's asking why there's no text in the standard making a diagnostic mandatory. In the former case, it would belpful to know which rule he thinks is violated by this code; in the latter case, it would be helpful to know what rule he thinks should be added to the standard. -- James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-10-14 06:34 -0700 |
| Message-ID | <1ca6ddab-c513-4095-92df-a81558006ad1@googlegroups.com> |
| In reply to | #72791 |
On Tuesday, October 13, 2015 at 10:12:32 PM UTC-5, James Kuyper wrote: > True - but diagnostics are always permitted.... I've often wondered what the purpose of the parts of the Standard which require a diagnostic in some cases, given that there's no requirement that an implementation provide any means of determining whether a program is found to have any constraint violations. A compiler which unconditionally output "WARNING: This program may contain constraint violations" or even "Note: program contained 473 characters" would satisfy the requirements but not be any more useful for purposes of noticing constraint violations than one that never output any diagnostics.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-10-14 10:26 -0700 |
| Message-ID | <lnsi5d8ip3.fsf@kst-u.example.com> |
| In reply to | #72832 |
supercat@casperkitty.com writes:
> On Tuesday, October 13, 2015 at 10:12:32 PM UTC-5, James Kuyper wrote:
>> True - but diagnostics are always permitted....
>
> I've often wondered what the purpose of the parts of the Standard which
> require a diagnostic in some cases, given that there's no requirement that
> an implementation provide any means of determining whether a program is
> found to have any constraint violations. A compiler which unconditionally
> output "WARNING: This program may contain constraint violations" or even
> "Note: program contained 473 characters" would satisfy the requirements
> but not be any more useful for purposes of noticing constraint violations
> than one that never output any diagnostics.
The standard does not, and probably cannot, require all implementations
to behave sensibly.
It requires at least one diagnostic for any translation unit containing
a violation of any syntax rule or constraint. A perverse conforming
compiler *could* print just a single diagnostic for every translation
unit and leave it at that, but such a compiler would not be useful.
In practice, it can be difficult to distinguish between required and
optional diagnostics, but with the right options you can usually assume
that any fatal error message denotes a serious problem, and any
non-fatal warning indicates somethuing that you should take a close look
at.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | MehdiAmini <atorrses@gmail.com> |
|---|---|
| Date | 2015-10-15 14:06 +0000 |
| Message-ID | <mvobsa$lf8$1@dont-email.me> |
| In reply to | #72791 |
In reply to "James Kuyper" who wrote the following:
[...]
> True - but diagnostics are always permitted. The OP seems to be be
> concerned about whether a diagnostic is mandatory for this code. It's
> not clear whether he's asking why this particular compiler fails to
> generate the diagnostic that he thought was mandatory, or whether he's
> asking why there's no text in the standard making a diagnostic
> mandatory. In the former case, it would belpful to know which rule he
> thinks is violated by this code; in the latter case, it would be helpful
> to know what rule he thinks should be added to the standard.
> --
> James Kuyper
After writing the original code, I found the following text in K&R:
"
A warning: printf uses its first argument to decide how many arguments follow
and what their type is. It will get confused,
and you will get wrong answers, if there are not enough arguments of if they are
the wrong type. You should also be aware of
the difference between these two calls:
printf(s); /* FAILS if s contains % */
printf("%s", s); /* SAFE */
"
--
--------------------------------- --- -- -
Posted with NewsLeecher v7.0 Beta 7
Web @ http://www.newsleecher.com/?usenet
------------------- ----- ---- -- -
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-10-15 10:26 -0400 |
| Message-ID | <mvocul$t70$1@dont-email.me> |
| In reply to | #72951 |
On 10/15/2015 10:06 AM, MehdiAmini wrote:
...
> After writing the original code, I found the following text in K&R:
>
> "
> A warning: printf uses its first argument to decide how many arguments follow
> and what their type is. It will get confused,
> and you will get wrong answers, if there are not enough arguments of if they are
> the wrong type. You should also be aware of
> the difference between these two calls:
> printf(s); /* FAILS if s contains % */
> printf("%s", s); /* SAFE */
> "
Note the key phrase: "if s contains %". Your string didn't contain any
'%' characters.
As I cited earlier, a format string is "composed of zero or more
directives: ordinary multi-byte characters (not %), which are copied
unchanged to the output stream, and conversion specifications, ...".
(7.21.6.1p3). The reason that % is excluded from "ordinary multi-byte
characters" is because every '%' character is interpreted as the start
of a conversion specifier. For every conversion specifier in the format
string, there should be an additional argument to printf() whose
promoted type matches that required by the conversion specifier (there
are exceptions, but you should learn the general rule, first). Since
your string doesn't contain any conversion specifiers, you don't need
any additional arguments.
Note that the failure to provide enough arguments has undefined behavior
- it is not a constraint violation or a syntax error, and the compiler
is therefore nor required to issue a diagnostic. Most modern compilers
will examine your format string if it is a string literal such "%s", and
give you an error message is you haven't provided arguments with a
promoted type that matches the one required by each specifier. However,
they're not required to provide those warning messages, and in general
they won't do such a check if the format string is stored in a character
array like "message", rather than string literal.
That's a reason to avoid storing the format string in a character array
- but there's nothing actually wrong about doing so. It just means that
the compiler won't be checking the validity of the format string, so you
have to be very careful to make sure it's valid yourself.
--
James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2015-10-25 23:02 +0100 |
| Message-ID | <n0jjed$9gp$1@dont-email.me> |
| In reply to | #72783 |
On 14/10/2015 04:55, glen herrmannsfeldt wrote: > James Kuyper <jameskuyper@verizon.net> wrote: > > (snip on printf with one argument) > >> <stdio.h> brings in a prototype declaration of printf() like the following: >> >> int printf(const char * restrict format, ...); (7.21.6.3p1) >> >> Such a prototype requires that: >> 1. The function be called with at least one argument. >> printf(message) meets that requirement >> 2. The type of that argument must be convertible to "const char*". >> The type of message is "const char*", and therefore trivially convertible. > > With compilers generating more and more warnings, possibly for things > that are actually correct, I would not be surprised to see a warning > for a single non-constant argument. And it is indeed possible to request such a warning from gcc: (Though it wouldn't fire in the OP's example) > -Wformat-security: If -Wformat is specified, also warn about uses of > format functions that represent possible security problems. At > present, this warns about calls to printf and scanf functions where > the format string is not a string literal and there are no format > arguments, as in printf(foo). This may be a security hole if the > format string came from untrusted input and contains ā%nā. (This is > currently a subset of what -Wformat-nonliteral warns about, but in > future warnings may be added to -Wformat-security that are not > included in -Wformat-nonliteral.) https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html Regards.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web