Can't print char!

J

JS

I would like to print char 'd':

main(){

char g[4];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';

char *pp;
pp = &g[3];

printf("%s", *pp);
getchar();

}

But its only possible to get d printed if I change:

printf("%s", *pp);

into:

printf("%s", pp);





But when I do the same thing with an int I have to use the first version of
the printf:

main(){

int j = 50;

int *q;

q = &j;

printf("%d", *q);
getchar();

}

Why is it the other way around with integers??

JS
 
S

simon danner

with %s in printf you print a string, represented by a pointer of the
first char. it is just luck that it prints out one char, if the
following address would have a value of nonzero, it would print out
garbage (-> a string is null terminated).
to print an integer, you need to dereference the pointer, because printf
needs the value, not the address.

simon
 
W

Walter Roberson

:I would like to print char 'd':

: char g[4];
: g[3] = 'd';

: pp = &g[3];

: printf("%s", *pp);

*pp is a single character, not a string. You should be using a %c
format to print it -- otherwise the -value- that 'd' corresponds to
will be used as a pointer to the string to print, with nasty results.

You also are making a mistake by using a %s format to deal with
a character array that is not NULL terminated.
printf("%s", pp); is going to run off the end of the string
which is a Bad Thing.
 
C

Christopher Benson-Manica

JS said:

Invalid in C99. main() returns int.
char g[4];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';
char *pp;
pp = &g[3];

pp points to the last element of g, which is a character.
printf("%s", *pp);

You probably meant

printf( "%c\n", *pp );
getchar();

Omitting the return statement of main() is not permitted in C89.
printf("%s", pp);


Very bad. The %s format specifier requires a null-terminated
array of characters, which pp is not. Undefined behavior results.

Why is it the other way around with integers??

Because you used the incorrect format specifier, as above.
 
E

Eric Sosman

JS said:
I would like to print char 'd':

main(){

char g[4];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';

char *pp;
pp = &g[3];

printf("%s", *pp);

The argument corresponding to "%s" must be a pointer
to character, a `char*'. However, `*pp' is not a pointer:
it is the character value that `pp' points to.

Furthermore, "%s" can't use a pointer to just any
character, but requires a pointer to the character at the
start of a string. A "string" is an array containing
some number of "payload" characters (perhaps zero of them)
followed by a character with the value zero, often written
as '\0'. Since the character sequence beginning with g[3]
doesn't fit this description (the one-character payload
is present, but there's no terminating '\0'), the character
pointer `pp' cannot be used where a string is expected.
That is, the "correction" to `printf("%s", pp)' would not
be a correction at all, just a different error.

What you probably want is one of

printf("%c", *pp);
printf("%.1s", pp);

.... and I'll refer you to your C textbook to figure out
what these mean.
 
K

Keith Thompson

You also are making a mistake by using a %s format to deal with
a character array that is not NULL terminated.
printf("%s", pp); is going to run off the end of the string
which is a Bad Thing.

Quibble: NUL terminated, not NULL terminated. NULL is a macro that
expands to a null pointer constant; NUL is the common name for the
null character '\0'.
 
K

Keith Thompson

Christopher Benson-Manica said:
JS <[email protected]> spoke thus: [...]
char g[4];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';
char *pp;
pp = &g[3]; [...]
printf("%s", pp);


Very bad. The %s format specifier requires a null-terminated
array of characters, which pp is not. Undefined behavior results.

A small quibble: %s requires *a pointer to the first character of* a
null-terminated array of characters. (If you give it an array name,
the name decays to a pointer to its first element.)

If not yet enlightened, see section 6 of the C FAQ.
 
M

Martin Ambuhl

JS said:
I would like to print char 'd':

main(){

char g[4];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';

char *pp;
pp = &g[3];

printf("%s", *pp);
^^
wrong specifier. %c is for characters
getchar();

}

But its only possible to get d printed if I change:
printf("%s", *pp);
into:
printf("%s", pp);
*pp is a char, pp is pointer to char, and it is in your code not
necessarily a pointer to a string, since you have no '\0' following
{'a','b','c','d'}. See the code below for an initialization with such a
'\0'.
But when I do the same thing with an int I have to use the first version of
the printf:

main(){
int j = 50;
int *q;
q = &j;
printf("%d", *q);
getchar();
}
Why is it the other way around with integers??


#include <stdio.h>

void first_main(void)
{
char g[] = "abcd";
char *pp = &g[3];
printf("g is at %p; pp = &g[3] is %p\n", (void *) g, (void *) pp);
printf("This prints the string containing "
"{'a','b','c','d',0}: \"%s\"\n", g);
printf("So does this: \"%s\"\n\n", g);
printf("This prints the string containing {'d',0}: \"%s\"\n", pp);
printf("This prints the character 'd': '%c'\n\n", *pp);
}


void second_main(void)
{
int j = 50;
int *q = &j;
printf("j is at %p; q = &j is %p\n", (void *) &j, (void *) q);
printf("This prints the int j: %d\n", j);
printf("This prints the int *(&j): %d\n", *(&j));
printf("This prints the int *(q = (&j)): %d\n\n", *q);
}

int main(void)
{
printf("[output]\n");
first_main();
second_main();
return 0;
}



[output]
g is at eff90; pp = &g[3] is eff93
This prints the string containing {'a','b','c','d',0}: "abcd"
So does this: "abcd"

This prints the string containing {'d',0}: "d"
This prints the character 'd': 'd'

j is at effa4; q = &j is effa4
This prints the int j: 50
This prints the int *(&j): 50
This prints the int *(q = (&j)): 50
 
J

Joe Wright

JS said:
I would like to print char 'd':

main(){

char g[4];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';

char *pp;
pp = &g[3];

printf("%s", *pp);
getchar();

}

But its only possible to get d printed if I change:

printf("%s", *pp);

into:

printf("%s", pp);





But when I do the same thing with an int I have to use the first version of
the printf:

main(){

int j = 50;

int *q;

q = &j;

printf("%d", *q);
getchar();

}

Why is it the other way around with integers??

JS

Study this..

/* I would like to print char 'd': */
#include <stdio.h>
int main()
{
char g[4];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';

char *pp;
pp = &g[3];

printf("%c", *pp);
return 0;
}
 
C

CBFalconer

JS said:
I would like to print char 'd':

main(){

int main(void) {
char g[4];

char g[5];
g[0] = 'a';
g[1] = 'b';
g[2] = 'c';
g[3] = 'd';

g[4] = '\0';

or replace the whole mess with:

char g[] = "abcd"; /* which will append the '\0' for you */
char *pp;
pp = &g[3];

printf("%s", *pp);

printf("%c", *pp); /* *pp is a char, not a string */
fflush(stdout);
getchar();

Pointless, except possibly to prevent an IDE window exiting.
Simpler to just run it from a command line window. You are still
missing:

return 0;
}

But its only possible to get d printed if I change:

printf("%s", *pp);
into:
printf("%s", pp);

without the g[4] = '\0' here you are running into undefined
behaviour. Strings require a terminating '\0'.
But when I do the same thing with an int I have to use the first version of
the printf:
.... snip ...

Why is it the other way around with integers??

Because C passes things by value, except arrays. Arrays are passed
by a pointer to the first member. A C string is an array of char,
with a terminal '\0' appended.
 
K

Keith Thompson

:> a character array that is not NULL terminated.

:Quibble: NUL terminated, not NULL terminated. NULL is a macro that
:expands to a null pointer constant; NUL is the common name for the
:null character '\0'.

http://www.unicode.org/Public/MAPPINGS/VENDORS/MISC/US-ASCII-QUOTES.TXT

# The entries are in ANSI X3.4 order.
#
0x00 0x0000 # NULL

Ok, but (1) NUL is an abbreviation for NULL, and is a more common name
for the character, and (2) NULL has a specific meaning in C, so using
the term for anything else *in comp.lang.c* should be avoided.
 
O

osmium

Walter Roberson said:
:> a character array that is not NULL terminated.

:Quibble: NUL terminated, not NULL terminated. NULL is a macro that
:expands to a null pointer constant; NUL is the common name for the
:null character '\0'.

http://www.unicode.org/Public/MAPPINGS/VENDORS/MISC/US-ASCII-QUOTES.TXT

# The entries are in ANSI X3.4 order.
#
0x00 0x0000 # NULL

I really dislike threads such as this, on the various meanings of nul, null,
NUL and NULL. But your reference is specious, the *official;* ASCII chart
lists the character with a value of binary zero as NUL. Not NULL, as your
link above says. The control codes were specified with a maximum of three
upper case letters. You can recognize the official document by it's red,
white and blue cover.
 
W

Walter Roberson

:the *official;* ASCII chart

:You can recognize the official document by it's red,
:white and blue cover.

Which edition? 1968? 1974? 1983?

I visited the ANSI online store, but the official X3.4 document is no
longer orderable; X3.48 is the closets they have.
 
O

osmium

Walter Roberson said:
:the *official;* ASCII chart

:You can recognize the official document by it's red,
:white and blue cover.

Which edition? 1968? 1974? 1983?

I visited the ANSI online store, but the official X3.4 document is no
longer orderable; X3.48 is the closets they have.

I don't know, I only have a Xerox copy of the one heavily used page that
mapped graphics to the binary representation. And it was in the company
library of a company which is now pretty much defunct. On the off chance
that this is not a rhetorical question, I think it highly unlikely that they
would change the spelling of NUL though. And a standard that changes the
spelling of the fundamental words is a sorry standard indeed. These things
are supposed to be critiqued *before* they become standards, not afterwards.
 
W

Walter Roberson

:On the off chance
:that this is not a rhetorical question, I think it highly unlikely that they
:would change the spelling of NUL though. And a standard that changes the
:spelling of the fundamental words is a sorry standard indeed.

A number of the control characters in ANSI underwent name changes, e.g.,
Data link escape, start of message, X-ON (DC1), X-OFF (DC3);
0x7e was an escape character... then there were the national character
positions (e.g., # vs pounds-stirling, [, |, ] vs aa, ae, oe).
ASCII did not really get nailed down until the early 1980's.
 
C

Christopher Benson-Manica

Keith Thompson said:
A small quibble: %s requires *a pointer to the first character of* a
null-terminated array of characters. (If you give it an array name,
the name decays to a pointer to its first element.)

I'm always glad to accept quibbles from gurus. Thanks.
 
O

osmium

Walter Roberson said:
:On the off chance
:that this is not a rhetorical question, I think it highly unlikely that
they
:would change the spelling of NUL though. And a standard that changes the
:spelling of the fundamental words is a sorry standard indeed.

A number of the control characters in ANSI underwent name changes, e.g.,
Data link escape, start of message, X-ON (DC1), X-OFF (DC3);
0x7e was an escape character... then there were the national character
positions (e.g., # vs pounds-stirling, [, |, ] vs aa, ae, oe).
ASCII did not really get nailed down until the early 1980's.

Well, if you know they changed the spelling of NUL to NULL why don't you
just *say so*? Why bring these other things up? Do these other things have
some bearing on the question at hand?
 
W

Walter Roberson

:> :On the off chance
:> :that this is not a rhetorical question, I think it highly unlikely that
:> they
:> :would change the spelling of NUL though. And a standard that changes the
:> :spelling of the fundamental words is a sorry standard indeed.

:> A number of the control characters in ANSI underwent name changes, e.g.,

:Well, if you know they changed the spelling of NUL to NULL why don't you
:just *say so*? Why bring these other things up? Do these other things have
:some bearing on the question at hand?

Those other changes, known for sure to have occured, undermine
confidence in the long term stability of the standard -- it definitely
*was* a "living standard", not something that was decided upon once and
never deviated from thereafter. "Highly unlikely" is an expression
of probability, and demonstration that other parts of the standard
definitely changes increases the probability that NUL/NULL might have
changed.

Was the spelling ever NULL for the name of the character (as opposed to
its abbreviation)? I do not know -- I don't have access to an official
copy, especially not to the 1968 edition or the drafts from 1965 thru
1968. My research online -hints- that the character -name- may have
appeared in all uppercase in the original edition. Most of the
references these days are to the character name as "Null" in mixed
case. -Plausibly- the typography changed early on. For example,
-plausibly- NULL appeared in one of the charts or appendices of
X3.4-1968. Printers with lower-case weren't nearly as common in 1968 as
they would be less than a decade later.
 

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

Forum statistics

Threads
474,161
Messages
2,570,891
Members
47,423
Latest member
henerygril

Latest Threads

Top