"%d"+1 and printf !!

K

karthikbalaguru

Hi,

I came across a strange code snippet.

int main(void)
{
printf("%d"+1,987);
return 0;
}

The output is d.

But, where should we need to use
the above method of printf ?

Any specific name for this method ?
Any ideas ?

Thx in advans,
Karthik Balaguru
 
R

Richard

karthikbalaguru said:
Hi,

I came across a strange code snippet.

int main(void)
{
printf("%d"+1,987);
return 0;
}

The output is d.

But, where should we need to use
the above method of printf ?

You shouldn't. It's horrible.
Any specific name for this method ?

Dangerous and poor style.
Any ideas ?

Yup, don't use it. It's almost certainly a typo or a troll. The "+"
moves the string pointer passed to printf() to point to the letter
d. Nothing clever or useful in that at all.
 
J

Jens Thoms Toerring

karthikbalaguru said:
I came across a strange code snippet.
int main(void)
{
printf("%d"+1,987);
return 0;
}
The output is d.
But, where should we need to use
the above method of printf ?

Hardy ever. Just because something is possible you don't
have to use it. You can also bite into your own finger
until it bleeds, but you rather likely don't do so most
of the time;-) It's just a demonstration that a format
string is just a string, including conversion to a poin-
ter to the first element when used in value context.
There are all kinds of such little tricks like writing
'"abc"[1]' when you want the character 'b' (or even
'1["abc"]') but just because you can do so doesn't make
it very useful in most everyday situations.

Regards, Jens
 
K

karthikbalaguru

karthikbalaguru said:
I came across a strange code snippet.
int main(void)
{
printf("%d"+1,987);
return 0;
}
The output is d.
But, where should we need to use
the above method of printf ?

Hardy ever. Just because something is possible you don't
have to use it. You can also bite into your own finger
until it bleeds, but you rather likely don't do so most
of the time;-) It's just a demonstration that a format
string is just a string, including conversion to a poin-
ter to the first element when used in value context.
There are all kinds of such little tricks like writing
'"abc"[1]' when you want the character 'b' (or even
'1["abc"]') but just because you can do so doesn't make
it very useful in most everyday situations.

If it is not useful, then i think those stuffs
should be removed or come under some
warnings or some error checking conditions
should be added to throw error inside printf .

I think, 'printf' has not been thoroughly tested
before release or some scenarios have been
overlooked while design/implementation ?

Any improvements/fixes under progress ?
Any ideas ?

Thx in advans,
Karthik Balaguru
 
B

Bartc

If it is not useful, then i think those stuffs
should be removed or come under some
warnings or some error checking conditions
should be added to throw error inside printf .

This is not really the compiler's job, otherwise where would it stop?

Is the following useful:

printf(" %d"+nospace,i); ?

If so how does the compiler tell the difference between this, and the OPs
code (remembering the 1 in +1 could be a macro expansion)?
 
G

Guest

you seem to be doing that a lot recently.
Where are you finding this horrible code?
Hardy ever. Just because something is possible you don't
have to use it. You can also bite into your own finger
until it bleeds, but you rather likely don't do so most
of the time;-) It's just a demonstration that a format
string is just a string, including conversion to a poin-
ter to the first element when used in value context.
There are all kinds of such little tricks like writing
'"abc"[1]' when you want the character 'b' (or even
'1["abc"]') but just because you can do so doesn't make
it very useful in most everyday situations.

If it is not useful, then i think those stuffs
should be removed or come under some
warnings or some error checking conditions
should be added to throw error inside printf .

except it isn't an error...

I think, 'printf' has not been thoroughly tested
before release or some scenarios have been
overlooked while design/implementation ?

Any improvements/fixes under progress ?
Any ideas ?

I think you misunderstand the philosophy behind C.
The idea is to be "close to the machine". The term
"portable assembler" is also used. Most C code compiles
on typical architectures to a small number of (fairly)
obvious machine instructions. Well at least until the optimiser
gets turned on. C does not try to protect you from yourself.
But gives a small number of powerful primitives and combination
rules and pretty well leaves you to it.

The upshot is that C standard is *not* going to be modifed
in the near future to fix these things which you perceive
to be bugs. Most of us get along by not doing really weird
things (unless we *really* need to). You are either going
to have to accept C as it is and learn to live with it.
Or find another language that better suits you. Ada maybe?


--
Nick Keighley

Most Ada programmers would consider going out of your way to
construct an Ada program that had a potential buffer overflow not as
a challenge, but as a kind of pornography.
 
J

Jens Thoms Toerring

karthikbalaguru said:
karthikbalaguru said:
I came across a strange code snippet.
int main(void)
{
printf("%d"+1,987);
return 0;
}
The output is d.
But, where should we need to use
the above method of printf ?

Hardy ever. Just because something is possible you don't
have to use it. You can also bite into your own finger
until it bleeds, but you rather likely don't do so most
of the time;-) It's just a demonstration that a format
string is just a string, including conversion to a poin-
ter to the first element when used in value context.
There are all kinds of such little tricks like writing
'"abc"[1]' when you want the character 'b' (or even
'1["abc"]') but just because you can do so doesn't make
it very useful in most everyday situations.
If it is not useful, then i think those stuffs
should be removed or come under some
warnings or some error checking conditions
should be added to throw error inside printf .

If you want a different language than C there are enough.
There are some rules in C that makes certain less common
constructs possible, but you don't have to use them (and
some of them can, in very special situations, become use-
ful). A compiler is free to spit out a warning if such an
unusual construct is used, but it's not mandated by the
C standard and, IMHO, shouldn't. C isn't a language that
holds your hand and keeps you from doing something stupid.
It tends to gives you enough rope to hang yourself - or
to make something extremely useful out of it. That may
make it a bit more difficult to learn and use C correctly
but, on the other hand, allows you to write effective,
fast code. That's why e.g. so many operating systems are
written in C.
I think, 'printf' has not been thoroughly tested
before release or some scenarios have been
overlooked while design/implementation ?

printf() can't be tested or released, it is a function
whose behaviour is defined by the C standard. There are
a number of *implementations* of this functions (in more
or less every libc) and some of those implementation may
have been more or less well tested. If you find a bug in
one of those implementations you have to take it up with
the writers of that implementation of printf(), it's not
a C issue.

BTW, if you're looking for more strange constructs and
(mis-?) uses of C look up the International Obfuscated
C Code Contest (IOCCC). Decide for yourself if you want
to learn/use a language that allows such things;-)

Regards, Jens
 
J

James Kuyper

karthikbalaguru said:
....
If it is not useful, then i think those stuffs
should be removed or come under some
warnings or some error checking conditions
should be added to throw error inside printf .

The standard imposes no restrictions on warnings, and there would be no
problem if an implementation provided some.
I think, 'printf' has not been thoroughly tested
before release or some scenarios have been
overlooked while design/implementation ?

printf() was designed more than 3 decades ago; it's been tested
constantly, both by actual test code and and by routine use in normal
operations. It wasn't standardized until 1989, and it's initial
specification at that time reflected all of that experience. The
standard was updated in 1999, and the revised specification reflected an
additional 10 years of experience with the routine. While it is not
perfect, I suspect that the issues you're worried about are not caused
by inadequate testing, but by the fact that you have a design philosophy
that differs from that of the committee.

The C language was not intended to be a language that protects you from
all possible mistakes. It's meant to be a low-level language that is
just a few steps up from being an assembler. As such, it provides basic
components that the developer can put together in a wide variety of
ways, most of which don't make any sense. It is the responsibility of
the programmer to choose to put those components together in a
meaningful, useful way.

To give you some insight into why the language is designed this way, I
would suggest that you try writing up a proposed change to the standard
that would make the subject code a constraint violation, and post it here.
 
C

CBFalconer

christian.bau said:
This kind of problem is usually not solved at the level of the
programming language, but on a more physical level, by removing
any programmer writing that kind of code to a different job
where they can't do any harm.

Do you think knifes and forks have been thoroughly tested, or do
you think their developers should be blamed because they have
overlooked the problem that you can stab yourself into your leg
with the fork and cut your fingers off with the knife?

YES. This is the last word in replies to this ridiculous thread.
It provides definitive solutions to all the problems.
 
R

Richard

CBFalconer said:
YES. This is the last word in replies to this ridiculous thread.
It provides definitive solutions to all the problems.

I can think of reasons why someone MIGHT use this TYPE of expression. I
would not recommend it generally. But to call this thread ridiculous is,
well, ridiculous. Especially from someone who is wrong more often than
right in his advice.
 
D

Dik T. Winter

> If it is not useful, then i think those stuffs
> should be removed or come under some
> warnings or some error checking conditions
> should be added to throw error inside printf .

You misunderstand. "%d"+1 is a proper character pointer, and that is just
what printf does expect. That is all, printf does know nothing about how
that character pointer was constructed. Moreover, printf does not know
how many arguments it receives, except that the format string specifies
how many arhuments to use.
 
R

Richard

Dik T. Winter said:
You misunderstand. "%d"+1 is a proper character pointer, and that is just
what printf does expect. That is all, printf does know nothing about how
that character pointer was constructed. Moreover, printf does not know
how many arguments it receives, except that the format string specifies
how many arhuments to use.

So it DOES know then ...
 
K

karthikbalaguru

printf() does not get to see how its arguments were computed. It
looks to printf() like it was called with a format string of "d",
which is perfectly legitimate. printf() cannot tell that it has
an extra unused argument using the facilities of <stdarg.h>. In
order to tell that it has an extra argument, it would have to use
some other method provided by the implementation.

A *compiler*, on the other hand, can tell this where the format
string given is a constant. gcc -Wall generates a warning on
the above printf() call.

Interesting :):)

Karthik Balaguru
 
I

Ike Naar

Dik T. Winter said:
[snip]
Moreover, printf does not know
how many arguments it receives, except that the format string specifies
how many arhuments to use.

So it DOES know then ...

Consider this:

printf("%d\n", 42, 43);

How does printf know about the second integer argument (the 43)?
 
C

CBFalconer

Ike said:
Richard said:
Dik T. Winter said:
[snip]

Moreover, printf does not know how many arguments it receives,
except that the format string specifies how many arhuments to use.

So it DOES know then ...

Consider this:
printf("%d\n", 42, 43);
How does printf know about the second integer argument (the 43)?

As usual Richard the nameless is wrong. And your addition is
marking the wrong thing. The point is that the format string is
just that - a string - which is passed to printf. That string may
have just been generated by other code, and then the compiler has
no reason to know what is in it. Since that string is the ONLY
thing that specifies the following parameters, the compiler cannot
know about them either. (Except in the exceptional case where the
string is a known constant string.)

In your example the second argument is harmless. printf will
ignore it. It does no harm, apart from occupying some parameter
passing space. printf decides on the parameters passed via the
format string, and the basic errors are specifying the wrong type
for a parameter, or failing to supply a specified parameter.
 
D

Dik T. Winter

Not having received the article to which I want to reply, I piggyback on
the one mentioned in the References header line:

....
No, it does *not* know. It know how many to use, not how many it receives.
It does not know whether the actual number of arguments is smaller or
greater than the number of arguments it has to use.
 
M

MisterE

Richard said:
You shouldn't. It's horrible.


Dangerous and poor style.


Yup, don't use it. It's almost certainly a typo or a troll. The "+"
moves the string pointer passed to printf() to point to the letter
d. Nothing clever or useful in that at all.

Is it actually dangerous though?
I have seen things like:

#define MY_STRING "three two one"
printf(MY_STRING + 6);
printf(MY_STRING + 9);
 
K

Kenny McCormack

That statement isn't supported by the standard. All we can conclude
from the standard is that printf() *may or may not* know how many
it receives.

And you don't need the standard for that.

(Simple logic tells us that for any X, the predicate: X or not X
has the constant value: true)

Ain't pedantry grand?
 
N

Nate Eldredge

MisterE said:
Is it actually dangerous though?
I have seen things like:

#define MY_STRING "three two one"
printf(MY_STRING + 6);
printf(MY_STRING + 9);

It's "dangerous" only in the sense that it's hard to read and maintain
(if you decide you need "four three two one" instead, you have to change
all the offsets). But it's perfectly legal and well defined. I can imagine it
being justified in a situation where memory is at a premium (so the
overhead of separately storing the strings "three two one", "two one"
and "one" is unacceptable), especially if the offsets are automatically
generated by some external tool. Or in an Obfuscated C Contest entry :)
 
P

Phil Carmody

Nate Eldredge said:
It's "dangerous" only in the sense that it's hard to read and maintain
(if you decide you need "four three two one" instead, you have to change
all the offsets).

#define MY_STRING ("four three two one"+5)

;-p

And yes, I have seen things like that.

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

%a in printf 6
Why do i get runtime error ? 19
Strange behaviour of while loop !! 14
For loop and strlen 8
++*p++ 24
Command Line Arguments 0
A different kind of subtraction ? 5
sequence points and printf() 17

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,135
Latest member
VeronaShap
Top