printf

B

biras

hi



#include<stdio.h>
void main( )
{
char *p;
p="yes";
printf(p);
}

output : yes


how printf is giving output ?
 
G

Grumble

biras said:
#include<stdio.h>
void main( )
{
char *p;
p="yes";
printf(p);
}

how printf is giving output ?

printf() printed what you asked for, i.e. a format string with no
conversion specifications.

Try the following.

extern int printf(const char *format, ...);
int main(void) {
const char format[] = "I AM A FORMAT STRING. %d IS AN INTEGER.\n";
printf(format, 42);
return 0;
}
 
F

Fao, Sean

biras said:
hi



#include<stdio.h>
void main( )
{
char *p;
p="yes";
printf(p);
}

output : yes


how printf is giving output ?

Because you got lucky?

What is this? A test to see how much UD you can cram into one small
program? Nearly every line has a mistake.
 
C

Cong Wang

biras said:
hi



#include<stdio.h>
void main( )
{
char *p;
p="yes";
printf(p);
}

output : yes


how printf is giving output ?
That depends on your operating system.Just a printf() function needs
many system calls.
 
C

Chris Dollin

Because you got lucky?

What is this? A test to see how much UD you can cram into one small
program? Nearly every line has a mistake.

There are five non-trivial lines, of which at most two contain a
mistake as far as I can see.
 
E

Emmanuel Delahaye

Sensei wrote on 29/07/05 :
You are *really* lucky it didn't crash. You are writing into a random portion
of memory.

Huh ? Why ? What's wrong here ?
You still have to allocate p.

'p' is pointing to a string literal which is anything but wrong. (Ok,
'char cont *p' could have been a better choice).


--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."
 
R

Robert Gamble

Sensei said:

Maybe legal, but hopefully not "normal".
#include said:
int main() as sombody said *very* correctly.

What's wrong with int main (void) ?
You are *really* lucky it didn't crash. You are writing into a random
portion of memory.

First off, this is perfectly fine, would you also object to char *p =
"yes"? If not, what do you think the difference is between the two?

Secondly, I think you would be lucky if writing to a "random portion of
memory" *did* crash your program, there are far worse things that could
happen like not realizing that there is a problem (which there isn't in
this case).
You still have to allocate p.

p has been allocated, what do you think the definition did? Do you
mean the space to which p points has not been allocated? If so, that
is also incorrect.
By luck now. If you correct the errors, by calling your OS syscalls.

I think you need to crack open your C book before trying to correct
someone again ;)

Robert Gamble
 
F

Fao, Sean

Chris said:
There are five non-trivial lines, of which at most two contain a
mistake as far as I can see.

You're right. I was being a dummy! It's been a while since I've done
any C programming and I forgot that p = "yes" was a legal assignment
because it just assigns a pointer to a string literal that the compiler
allocated space for.

Please pardon my "idiotness" while I get back into the swing of things.
I'll try not to be such a dummy in the future!
 
S

Sensei

Maybe legal, but hopefully not "normal".
#include <stdio.h> is much preferred.

Of course, but it's legal :)
What's wrong with int main (void) ?


I meant, int instead of void, as somebody said correctly.

First off, this is perfectly fine, would you also object to char *p =
"yes"? If not, what do you think the difference is between the two?


That the first is statically allocated and the second uses a non
allocated memory? I was always taught not to use the second form, since
you can access random memory.

The problem is that one can do this thing also, thinking that p is
correctly working:

#include <stdio.h>

int main(void)
{
char *p;
int i;

for (i = 0; i <= 1024; i++)
p = 'A';

printf(p);
return 0;
}

And of course, it causes bad problems. A pointer is there, but the
memory which it points to may not belong to you...

This is why I was always told not to separate the two things: it can be
disguising.
Secondly, I think you would be lucky if writing to a "random portion of
memory" *did* crash your program, there are far worse things that could
happen like not realizing that there is a problem (which there isn't in
this case).


p has been allocated, what do you think the definition did? Do you
mean the space to which p points has not been allocated? If so, that
is also incorrect.

p yes, but afaik just the pointer and not the chars... wouldn't be
correct to use

char *p = "balh"; OR char p[] OR p[aNumber]

or malloc p before allocating space for the string.
I think you need to crack open your C book before trying to correct
someone again ;)

I'm here to learn more and be corrected, if I'm wrong I'm happy to learn! :)
 
C

Chris Dollin

Sensei said:
You are *really* lucky it didn't crash. You are writing into a random
portion of memory.

No, he isn't. He's writing a character pointer (the result of "yes")
into a character pointer variable (p). If he had written

*p = 'y';

you'd have been right.
 
J

John Bode

Sensei said:
Of course, but it's legal :)



I meant, int instead of void, as somebody said correctly.




That the first is statically allocated and the second uses a non
allocated memory? I was always taught not to use the second form, since
you can access random memory.

Both

char *p = "yes";

and

char *p;
p = "yes";

do the exact same thing: the string literal "yes" is statically
allocated in non-writable memory, and its pointer value is assigned to
p (not to a location pointed to by p). For the sake of illustration,
assume that the string literal "yes" is stored at memory location
0x8000. Then the statements above are equivalent to

char *p = 0x8000;

and

char *p;
p = 0x8000;


It's not any different from doing

int i;
int *p;
p = &i;

You wouldn't say that last assignment was a problem, would you?

What you *don't* want to do is anything like

char *p;
strcpy(p, "yes");

or

char *p;
p[0] = 'y';
p[1] = 'e';
p[2] = 's';

because then you are attempting to write to the location that p *points
to*, which is invalid.

The only hitch with

char *p = "yes";

is that string literals are not writable, so doing something like

char *p = "yes";
strcpy(p, "no");

or

p[0] = 'Y';

would be illegal.

[snip]
p has been allocated, what do you think the definition did? Do you
mean the space to which p points has not been allocated? If so, that
is also incorrect.

p yes, but afaik just the pointer and not the chars... wouldn't be
correct to use

char *p = "balh"; OR char p[] OR p[aNumber]

or malloc p before allocating space for the string.

The space for the string has *already been allocated* by virtue of the
string literal; somewhere in (non-writable) memory is a char buffer
with the contents "yes", and the location of that buffer is what's
being assigned to p. Whether it's assigned as an initializer in the
definition of p or as a separate assignment statement doesn't matter.
 
S

Sensei

Both

char *p = "yes";

and

char *p;
p = "yes";

do the exact same thing: the string literal "yes" is statically
allocated in non-writable memory, and its pointer value is assigned to
p (not to a location pointed to by p).


Good to know, I had the feeling it was so, but I was taught otherwise...

For the sake of illustration,
assume that the string literal "yes" is stored at memory location
0x8000. Then the statements above are equivalent to

char *p = 0x8000;

and

char *p;
p = 0x8000;


I see, this explains better.

It's not any different from doing

int i;
int *p;
p = &i;

You wouldn't say that last assignment was a problem, would you?


No, I wouldn't say it's a problem.

What you *don't* want to do is anything like

char *p;
strcpy(p, "yes");

or

char *p;
p[0] = 'y';
p[1] = 'e';
p[2] = 's';

because then you are attempting to write to the location that p *points
to*, which is invalid.


That's what I knew, of course :)

The only hitch with

char *p = "yes";

is that string literals are not writable, so doing something like

char *p = "yes";
strcpy(p, "no");

or

p[0] = 'Y';

would be illegal.


Yes, this is understandable. I didn't doubt it, i thought the other way
was illegal, but your example with a direct pointer is clear.

The space for the string has *already been allocated* by virtue of the
string literal; somewhere in (non-writable) memory is a char buffer
with the contents "yes", and the location of that buffer is what's
being assigned to p. Whether it's assigned as an initializer in the
definition of p or as a separate assignment statement doesn't matter.


Thanks! It's good to learn many things, and learn that what you've
taught doesn't mean a thing :D
 
K

Keith Thompson

John Bode said:
Both

char *p = "yes";

and

char *p;
p = "yes";

do the exact same thing: the string literal "yes" is statically
allocated in non-writable memory, and its pointer value is assigned to
p (not to a location pointed to by p).

The memory is non-writable only in the sense that attempting to write
to it invokes undefined behavior. The memory may actually be
read-only, but it doesn't have to be. A conforming implementation
*can* accept the following code:

char *p = "yes";
p[0] = 'Y';
puts(p);

and produce the output "Yes". It can also legally print "No" or,
more likely, abort the program.

[...]
The only hitch with

char *p = "yes";

is that string literals are not writable, so doing something like

char *p = "yes";
strcpy(p, "no");

or

p[0] = 'Y';

would be illegal.

Again, it's illegal only in the sense that it invokes undefined
behavior. The implementation is not required to diagnose the error.
 
J

John Bode

Keith said:
John Bode said:
Both

char *p = "yes";

and

char *p;
p = "yes";

do the exact same thing: the string literal "yes" is statically
allocated in non-writable memory, and its pointer value is assigned to
p (not to a location pointed to by p).

The memory is non-writable only in the sense that attempting to write
to it invokes undefined behavior. The memory may actually be
read-only, but it doesn't have to be. A conforming implementation
*can* accept the following code:

char *p = "yes";
p[0] = 'Y';
puts(p);

and produce the output "Yes". It can also legally print "No" or,
more likely, abort the program.

Sigh. Of course, you're right. I tend to conflate "undefined
behavior" with "yakking code", even though that's not universally true.
It's just every time I've run into this particular issue I get a core
dump, so I tend to think of string literals as non-writable in the
sense of an illegal access, rather than UB.

[snip rest]
 
C

Chris Croughton

Sigh. Of course, you're right. I tend to conflate "undefined
behavior" with "yakking code", even though that's not universally true.

It's not even usually true (there are many sorts of UB which will rarely
give any sort of warning, most arithmetic ones on integers for
instance). On most of the target platforms I use there is no memory
protection (other than if you write into ROM or unallocated addresses
nothing at all happens).
It's just every time I've run into this particular issue I get a core
dump, so I tend to think of string literals as non-writable in the
sense of an illegal access, rather than UB.

That only happens on a few systems I use (most of them x86 based, and
not on all of those). Some will happily change the data, some will
ignore the changes, only the host systems put string constants into an
area which faults if it is written.

And of course even on systems which do have that sort of protection it's
quite possible for an unititialised pointer to be pointing into
somewhere in R/W memory. Especially, it seems, under a debugger
(program crashes when run normally, run it under a debugger and it works
fine). Although that could just be the Irishmen...

Chris C
 
C

CBFalconer

John said:
.... snip ...

Both
char *p = "yes";
and
char *p;
p = "yes";

do the exact same thing: the string literal "yes" is statically
allocated in non-writable memory, and its pointer value is assigned
to p (not to a location pointed to by p). For the sake of ...

The best way to ensure no silly further errors is to type p as
"const char*". That will ensure that any attempt to modify the
string is a compile time error. Gcc can be told to do this
automatically (-Wwrite-strings). The only reason I can see not to
do so is to handle legacy code.

You can then still stuff p with a pointer to a writeable string,
you just won't be able to write to it. If your code requires both
usages you are just asking for maintenance trouble.
 

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

Members online

No members online now.

Forum statistics

Threads
474,167
Messages
2,570,911
Members
47,453
Latest member
MadelinePh

Latest Threads

Top