By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,938 Members | 1,584 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,938 IT Pros & Developers. It's quick & easy.

Query on pointers

P: n/a
What's wrong with this program? If you were to fix it, what would the
intended output be?

void swap(char *str, int index1, int index2) {
char tmp = str[index1];
str[index1] = str[index2];
str[index2] = tmp;
}

int main(int argc, char *argv[]) {
char *planet1;
char *planet2;

planet1 = (char *) malloc(7 * sizeof(char));
if (!planet1)
return 0;

snprintf(planet1, 7, "Jupiter");
planet2 = "Saturn";

swap(planet1, 0, 3);
swap(planet2, 3, 4);

printf("results: %s and %s\n", planet1, planet2);
return 0;
}

My interpretation : In turboc3 compiler(though it is a dead compiler
now) this problem is perfectly fine and we
get the o/p :

results: iupJter and Satrun

But in Bloodshed Dev C++ the code compiles fine but on
execution there is an error report generated.

swap(planet1,0,3) works fine but there is some problem
with swap(planet2,3,4)

Only when i allocate space for planet2 and perform
snprintf on planet2 i get the expected result.

Why do we need snprintf in this case....why does
planet2="Saturn" not work?

PS:Pls send your comments and correct me if i am wrong...i am working
on this problem for 2 long days.

May 4 '07 #1
Share this Question
Share on Google+
16 Replies


P: n/a
aj**********@gmail.com wrote:
What's wrong with this program? If you were to fix it, what would the
intended output be?

void swap(char *str, int index1, int index2) {
char tmp = str[index1];
str[index1] = str[index2];
str[index2] = tmp;
}

int main(int argc, char *argv[]) {
char *planet1;
char *planet2;

planet1 = (char *) malloc(7 * sizeof(char));
"Jupiter" is 7 characters, so you must allocate 8. Why? You figure it out...

if (!planet1)
return 0;

snprintf(planet1, 7, "Jupiter");
Use strcpy().

planet2 = "Saturn";
Here planet2 points to a string literal, which in most cases is
non-modifiable.
..
>
swap(planet1, 0, 3);
swap(planet2, 3, 4);
And here you write to planet2. That's not a good idea, as you discovered.
HTH
Bjørn
[snip]
May 4 '07 #2

P: n/a
On 4 May, 14:28, ajinkya.c...@gmail.com wrote:
What's wrong with this program?
It's broken...
If you were to fix it, what would the intended output be?
I don't know. It's not my program.
void swap(char *str, int index1, int index2) {
char tmp = str[index1];
str[index1] = str[index2];
str[index2] = tmp;
}
int main(int argc, char *argv[]) {
char *planet1;
char *planet2;

planet1 = (char *) malloc(7 * sizeof(char));
I would suggest that you don't cast the result of malloc - use
<stdlib.h- see FAQ http://c-faq.com/malloc/mallocnocast.html.

sizeof(char) is by definition, I believe, 1, so it served no purpose.

You've allocated 7 characters for planet1.
if (!planet1)
return 0;

snprintf(planet1, 7, "Jupiter");
"Jupiter" is not actually 7 characters long, is it? The result in the
space pointed to by planet1 will be "Jupite" (plus the obligatory
trailing '\0';

Why you felt the need to use snprintf() rather than strcpy(), or
strncpy(), I can't imagine.

If you use snprintf(), shouldn't you include <stdio.h>?
planet2 = "Saturn";
planet2 points to data which may well be read-only...
swap(planet1, 0, 3);
This will swap the "J" and "i" in "Jupite".
swap(planet2, 3, 4);
On my system, as I'd expected, this crashes with segmentation
violation, as you try to modify data in read-only memory.
printf("results: %s and %s\n", planet1, planet2);
return 0;

}
My interpretation : In turboc3 compiler(though it is a dead compiler
now) this problem is perfectly fine and we
get the o/p :

results: iupJter and Satrun
Really? turboc3 is broken in that case, as the 1st planet cannot
legitimately be "Jupiter" ...
But in Bloodshed Dev C++ the code compiles fine but on
execution there is an error report generated.

swap(planet1,0,3) works fine but there is some problem
with swap(planet2,3,4)

Only when i allocate space for planet2 and perform
snprintf on planet2 i get the expected result.

Why do we need snprintf in this case....why does
planet2="Saturn" not work?
See my comments above on read-only memory.

May 4 '07 #3

P: n/a
aj**********@gmail.com wrote:
What's wrong with this program? If you were to fix it, what would the
intended output be?
Whatever the redesigned program was written to output.

It is obviously wrong to omit
#include <stdlib.h>
#include <stdio.h>
void swap(char *str, int index1, int index2) {
char tmp = str[index1];
str[index1] = str[index2];
str[index2] = tmp;
}

int main(int argc, char *argv[]) {
char *planet1;
char *planet2;

planet1 = (char *) malloc(7 * sizeof(char));
The cast is unnecessay and bad programming practice.
sizeof(char) is by definition 1.
If you want no more flexibility than your code,
planet1 = malloc(7);
The magic number '7' is a bad idea, of course.
if (!planet1)
return 0;

snprintf(planet1, 7, "Jupiter");
planet2 = "Saturn";
Replace all of the above with
char planet1[] = "Jupiter";
char planet2[] = "Saturn";
>
swap(planet1, 0, 3);
swap(planet2, 3, 4);
You have just tried to modify a string literal. This is a very bad idea
and has unpredicatable consequences. One possible one is a program
crash. If you replace all of the code in main before the swap with the
two lines I suggested, this problem will not arise.
>
printf("results: %s and %s\n", planet1, planet2);
return 0;
}

My interpretation : In turboc3 compiler(though it is a dead compiler
now) this problem is perfectly fine and we
That TurboC allowed you to get away with this is just bad luck. It
would have been better for you if your program has crashed.
get the o/p :

results: iupJter and Satrun

But in Bloodshed Dev C++ the code compiles fine but on
execution there is an error report generated.
Because you foolishly try to modify a string literal.
>
swap(planet1,0,3) works fine but there is some problem
with swap(planet2,3,4)
No kidding.
Only when i allocate space for planet2 and perform
snprintf on planet2 i get the expected result.

Why do we need snprintf in this case....why does
planet2="Saturn" not work?
You don't need snprintf(). In addition to my suggested replacement
above, any of strcpy, memcpy, memmove, and sprintf could have been used.
There are other choices as well.
planet2 = "Saturn";
*does* work. It points planet2 to a string literal. It is you attempt
to modify the string literal that fails.
>
PS:Pls send your comments and correct me if i am wrong...i am working
on this problem for 2 long days.
You could have just checked the FAQ articles on the difference between
pointers and arrays in minutes, or even (horrors) read your textbook,
preventing the waste of 2 long days.
May 4 '07 #4

P: n/a
aj**********@gmail.com wrote:
>
What's wrong with this program? If you were to fix it, what would the
intended output be?

void swap(char *str, int index1, int index2) {
char tmp = str[index1];
str[index1] = str[index2];
str[index2] = tmp;
}

int main(int argc, char *argv[]) {
char *planet1;
char *planet2;

planet1 = (char *) malloc(7 * sizeof(char));
if (!planet1)
return 0;

snprintf(planet1, 7, "Jupiter");
planet2 = "Saturn";

swap(planet1, 0, 3);
swap(planet2, 3, 4);

printf("results: %s and %s\n", planet1, planet2);
return 0;
}
Question: What should the final printf() do with planet1, which
was allocated 7 bytes, all of which were filled with something
other than '\0'?
My interpretation : In turboc3 compiler(though it is a dead compiler
now) this problem is perfectly fine and we
get the o/p :

results: iupJter and Satrun
You got (un)lucky in that it gave the results you expected, rather
than crashing.
But in Bloodshed Dev C++ the code compiles fine but on
execution there is an error report generated.
It found the errors that TurboC3 failed to crash on.
swap(planet1,0,3) works fine but there is some problem
with swap(planet2,3,4)
planet2 is a pointer to a string literal, which may be placed in
read-only memory.
Only when i allocate space for planet2 and perform
snprintf on planet2 i get the expected result.
By making that change, you have guaranteed that the memory it points
to is writable. (Assuming that malloc worked, of course.)
Why do we need snprintf in this case....why does
planet2="Saturn" not work?
See above. The string "Saturn" can be placed in read-only memory.
PS:Pls send your comments and correct me if i am wrong...i am working
on this problem for 2 long days.
Who is "Pls"?

The ancient turboc3 compiler (16-bit real mode?) didn't place the
string literal into read-only memory. (There was no such thing in
the x86's "real mode" memory scheme, unless it was something like
ROM.) The Bloodshed Dev C++ complier probably runs in "protected
mode" on the x86 CPU, allowing it to place code and data in read-
only memory.

Also, your 7-byte buffer for the 8-byte string "Jupiter" (with the
'\0' terminator) "works" only by luck. The runtime library is
probably allocating more than 7 bytes, in order to handle proper
alignment, so you happen to have additional memory after your 7
bytes, and the 8th byte happens to be zero. Otherwise, the final
printf() wouldn't have stopped after the 7 characters "iupJter".
It would have kept going until it hit a '\0' or crashed.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

May 4 '07 #5

P: n/a
On 4 May, 15:23, Kenneth Brody <kenbr...@spamcop.netwrote:
Also, your 7-byte buffer for the 8-byte string "Jupiter" (with the
'\0' terminator) "works" only by luck. The runtime library is
probably allocating more than 7 bytes, in order to handle proper
alignment, so you happen to have additional memory after your 7
bytes, and the 8th byte happens to be zero. Otherwise, the final
printf() wouldn't have stopped after the 7 characters "iupJter".
It would have kept going until it hit a '\0' or crashed.
I think, indeed I'm fairly sure, you are mistaken.

The snprintf() call will move "Jupite" into the buffer allocated, and
then add the null character to make it a legal C string.

Either the original poster is mistaken about the output from turboc,
or it's broken.

May 4 '07 #6

P: n/a
ak
On May 4, 7:36 am, mark_blue...@pobox.com wrote:
On 4 May, 15:23, Kenneth Brody <kenbr...@spamcop.netwrote:
Also, your 7-byte buffer for the 8-byte string "Jupiter" (with the
'\0' terminator) "works" only by luck. The runtime library is
probably allocating more than 7 bytes, in order to handle proper
alignment, so you happen to have additional memory after your 7
bytes, and the 8th byte happens to be zero. Otherwise, the final
printf() wouldn't have stopped after the 7 characters "iupJter".
It would have kept going until it hit a '\0' or crashed.

I think, indeed I'm fairly sure, you are mistaken.

The snprintf() call will move "Jupite" into the buffer allocated, and
then add the null character to make it a legal C string.

Either the original poster is mistaken about the output from turboc,
or it's broken.
Check it on any "decent" compiler snprintf() moves "Jupiter" and not
"Jupite" ....i think you are mistaken.
May 4 '07 #7

P: n/a
ak <aj**********@gmail.comwrote:
>Check it on any "decent" compiler snprintf() moves "Jupiter" and not
"Jupite" ....i think you are mistaken.
#include <stdio.h>

int main(void)
{
char s[10];
snprintf(s, 7, "%s", "Jupiter");
printf("\"%s\"\n", s);
return 0;
}

$ cc --version
cc (GCC) 3.4.6

$ foo
"Jupite"

C99 7.19.6.5p2, The snprintf Function:
# output characters beyond the n-1st are discarded rather than being
# written to the array, and a null character is written at the end of
# the characters actually written into the array.

-Beej

May 4 '07 #8

P: n/a
ak wrote:
>
Check it on any "decent" compiler snprintf() moves "Jupiter" and not
"Jupite" ....i think you are mistaken.
Then you have a strange notion of 'decent compiler'.
Any *conforming* implementation, will truncate the string to "Jupite",
as that is what the standard requires for snprintf().

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
May 4 '07 #9

P: n/a
On May 4, 10:13 am, Bart van Ingen Schenau <b...@ingen.ddns.info>
wrote:
ak wrote:
Check it on any "decent" compiler snprintf() moves "Jupiter" and not
"Jupite" ....i think you are mistaken.

Then you have a strange notion of 'decent compiler'.
Any *conforming* implementation, will truncate the string to "Jupite",
as that is what the standard requires for snprintf().

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ:http://www.comeaucomputing.com/learn/faq
c.l.c FAQ:http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ:http://www.parashift.com/c++-faq-lite/
wont you call Bloodshed Dev C++ a "decent" compiler.......i know
ideally any compiler should not do it but all the compilers i have do
it("Jupiter")
May 4 '07 #10

P: n/a
ma**********@pobox.com wrote:
On 4 May, 15:23, Kenneth Brody <kenbr...@spamcop.netwrote:
>Also, your 7-byte buffer for the 8-byte string "Jupiter" (with the
'\0' terminator) "works" only by luck. The runtime library is
probably allocating more than 7 bytes, in order to handle proper
alignment, so you happen to have additional memory after your 7
bytes, and the 8th byte happens to be zero. Otherwise, the final
printf() wouldn't have stopped after the 7 characters "iupJter".
It would have kept going until it hit a '\0' or crashed.

I think, indeed I'm fairly sure, you are mistaken.

The snprintf() call will move "Jupite" into the buffer allocated,
and then add the null character to make it a legal C string.

Either the original poster is mistaken about the output from turboc,
or it's broken.
It probably worked because malloc allocated a multiple of 8 (or 4)
bytes. No guarantees.

And no, the snprintf doesn't know the size of the buffer. All it
has is what you tell it, and pointers to the buffer beginning. It
wasn't designed to handle strings.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
<http://kadaitcha.cx/vista/dogsbreakfast/index.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

May 4 '07 #11

P: n/a
Ajinkya wrote:
On May 4, 10:13 am, Bart van Ingen Schenau <b...@ingen.ddns.info>
wrote:
>ak wrote:
Check it on any "decent" compiler snprintf() moves "Jupiter" and
not "Jupite" ....i think you are mistaken.

Then you have a strange notion of 'decent compiler'.
Any *conforming* implementation, will truncate the string to
"Jupite", as that is what the standard requires for snprintf().

Bart v Ingen Schenau

wont you call Bloodshed Dev C++ a "decent" compiler.......i know
ideally any compiler should not do it but all the compilers i have do
it("Jupiter")
I call it a non-conforming (C99) implementation.
Which does not surprise me, because to my knowledge, it does not claim
conformance to C99.

Whether it is a "decent" implementation, depends on how it copes with
things like this:

* * char planet1[7];
* * snprintf(planet1, 7, "Jupiter (The big red planet in our solar
system)");

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
May 6 '07 #12

P: n/a
Bart van Ingen Schenau said:

<snip>
Whether it is a "decent" implementation, depends on how it copes with
things like this:

char planet1[7];
snprintf(planet1, 7, "Jupiter (The big red planet in our solar
system)");
This is rather like judging whether a Formula One car is "decent" by
smacking it into the wall at 200mph to see if the air-bag goes off.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 6 '07 #13

P: n/a
ma**********@pobox.com wrote:
>
On 4 May, 15:23, Kenneth Brody <kenbr...@spamcop.netwrote:
Also, your 7-byte buffer for the 8-byte string "Jupiter" (with the
'\0' terminator) "works" only by luck. The runtime library is
probably allocating more than 7 bytes, in order to handle proper
alignment, so you happen to have additional memory after your 7
bytes, and the 8th byte happens to be zero. Otherwise, the final
printf() wouldn't have stopped after the 7 characters "iupJter".
It would have kept going until it hit a '\0' or crashed.

I think, indeed I'm fairly sure, you are mistaken.

The snprintf() call will move "Jupite" into the buffer allocated, and
then add the null character to make it a legal C string.

Either the original poster is mistaken about the output from turboc,
or it's broken.
Well, some further investigation shows that the FreeBSD man pages say:

The snprintf() and vsnprintf() functions will write at most size-1
of the characters printed into the output string (the size'th
character then gets the terminating `\0'); [...] The output is
always null-terminated.

It also says that snprintf() is C99.

My C90 implementation doesn't even have snprintf(). However, it does
have an _snprintf(), which says:

The _snprintf function formats and stores count or fewer characters
and values (including a terminating null character that is always
appended unless count is zero or the formatted string length is
greater than or equal to count characters) in buffer.

So, it appears that a C99 implementation would put "Jupite". However,
a pre-C99 implementation is not required to do so. Given the fact
that the OP said the output included the 'r' in "iupJter", my guess is
that it is not a C99 implementation, and is not nul-terminating the
string.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

May 6 '07 #14

P: n/a
On May 5, 1:28 am, ajinkya.c...@gmail.com wrote:
What's wrong with this program? If you were to fix it, what would the
intended output be?
Slightly strange question, as who can know the intended output
except for the person who wrote it?
planet1 = (char *) malloc(7 * sizeof(char));
snprintf(planet1, 7, "Jupiter");
Something nobody has mentioned yet: you failed to write:
#include <stdlib.h>
#include <stdio.h>

so the above lines cause undefined behaviour.

(Sometimes it can be assumed that these includes were omitted
for brevity, but I don't feel confident the OP knows that these lines
are required).

May 6 '07 #15

P: n/a
On May 5, 1:58 am, mark_blue...@pobox.com wrote:
On 4 May, 14:28, ajinkya.c...@gmail.com wrote:
If you were to fix it, what would the intended output be?

I don't know. It's not my program.
planet1 = (char *) malloc(7 * sizeof(char));
if (!planet1)
return 0;
snprintf(planet1, 7, "Jupiter");

Why you felt the need to use snprintf() rather than strcpy(), or
strncpy(), I can't imagine.
I'm surprised that multiple people made this comment. strcpy
and strncpy would both cause the program to have undefined
behaviour (assuming appropriate headers are included in
all cases, that is).

As it is, snprintf will not cause UB. Conceivably the result is
not the inteded one -- but as you pointed out, we can't know
what the intended result even was.

May 6 '07 #16

P: n/a
Old Wolf said:
On May 5, 1:58 am, mark_blue...@pobox.com wrote:
>On 4 May, 14:28, ajinkya.c...@gmail.com wrote:
planet1 = (char *) malloc(7 * sizeof(char));
if (!planet1)
return 0;
snprintf(planet1, 7, "Jupiter");

Why you felt the need to use snprintf() rather than strcpy(), or
strncpy(), I can't imagine.

I'm surprised that multiple people made this comment. strcpy
and strncpy would both cause the program to have undefined
behaviour (assuming appropriate headers are included in
all cases, that is).
Never mind strcpy, strncpy, and snprintf - why he felt the need to use
malloc is beyond me. Simple arrays of char would have done the trick.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 6 '07 #17

This discussion thread is closed

Replies have been disabled for this discussion.