C novice question...

H

herrcho

#include <stdio.h>

int main()
{
int i;
char *p="sarang";
for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf(p);
char *k=p;
k[1]='u';
printf("%s",p);
}

i compiled it with gcc, and it shows error message,

i think the last 3 lines are problem.. Can anyone help me ?
 
C

Capstar

Next time, try to include the error message so we can use it to
determine the problem.
#include <stdio.h>

int main()
{
int i;
char *p="sarang";
char *k;
for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf(p);
/*char *k=p;*/ k=p;

k[1]='u';
printf("%s",p);
}

i compiled it with gcc, and it shows error message,

i think the last 3 lines are problem.. Can anyone help me ?


This will compile with warnings, but won't run properly because of the
k[1]='u' line.
To solve this change
char *p="sarang";
in
char p[]="sarang";

The p[] version causes memory for "sarang" to be allocated on the stack.
Your version hard codes "sarang" in the .rodata section of your program,
which is not writable.

Figure the last warning gcc gives you out yourself, it is informative
enough.

Mark
 
J

Jens.Toerring

herrcho said:
#include <stdio.h>
int main()
{
int i;
char *p="sarang";
for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf(p);
char *k=p;
k[1]='u';
printf("%s",p);
}


You promised that the program would return an int, but you
don't keep it... Better add a return statement.
i compiled it with gcc, and it shows error message,
i think the last 3 lines are problem.. Can anyone help me ?

Due to the line

char *p="sarang";

p is pointing to what's called a literal string, i.e. a string that
resides somewhere in memory which you aren't allowed to modify (it
actually may get placed in ROM or the compiler could use the same
memory if e.g. you would write

char *p1="sarang";
char *p2="arang";

with p2 being just p1 + 1). Now you make k point to the same
memory location and then try to change what's stored there. And
that's the problem because you're not allowed to do this.

The simplest way around this problem is to make p a real array,
not just a pointer:

char p[ ] = "sarang";

p is now an array with memory that belongs to your program and
initialized to "sarang". Since you own the memory you also can
change it without any problems. p (without any additions) can
still be treated like a pointer to the first element of the array
in most cases, so the rest of the program will still work without
modifications.
Regards, Jens
--
_ _____ _____
| ||_ _||_ _| (e-mail address removed)-berlin.de
_ | | | | | |
| |_| | | | | | http://www.physik.fu-berlin.de/~toerring
\___/ens|_|homs|_|oerring
 
L

Lew Pitcher

#include <stdio.h>

int main()
{
int i;
char *p="sarang";
for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf(p);
char *k=p;


Unless you are running a C99 compiler, the above statement is illegal.
Declarations cannot be mixed with statements; they must preceed the statements
in a block.

Move the declaration of k (char *k=p;) to the line immediately following the
declaration of p (char *p="sarang";)
k[1]='u';
printf("%s",p);
}

i compiled it with gcc, and it shows error message,

i think the last 3 lines are problem.. Can anyone help me ?

--
Lew Pitcher
IT Consultant, Enterprise Technology Solutions
Toronto Dominion Bank Financial Group

(Opinions expressed are my own, not my employers')
 
R

Robert Stankowic

herrcho said:
#include <stdio.h>

int main()
{
int i;
char *p="sarang";
p now points to the first character in a string literal, which is by
definition read only
for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf(p);
char *k=p;

the definition of k must be before any executable statement, unless you have
a C99 compiler.
k now points to the same read - only string
k[1]='u';
you try to write to this string -- bang.
printf("%s",p);
you defined correctly main() returning an int, so better return one:
return 0;
or, if you #include stdlib.h, you can write the more descriptive
return EXIT_SUCCESS;
btw, if you want to be sure that the result of your printf() statements
shows up immidiately, either append a '\n' to the format string or put a
fflush(stdout) after the printf()
i compiled it with gcc, and it shows error message,
segfault?
next time please be a little bit more precise:
was it a compiler diagnostic or did the program crash?
and what _was_ the exact error message?
i think the last 3 lines are problem.. Can anyone help me ?

Here is a corrected version of your code:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int i;
char p[] = "sarang";
char *k;

for(i = 0; i < 4; i++)
printf("%c", *(p+i));
printf("\n");

for(i = 0; i < 4; i++)
printf("%c", p);
printf("\n");
printf(p);
printf("\n");

k = p;
k[1] = 'u';
printf("%s", p);
fflush(stdout);
return EXIT_SUCCESS;
}

HTH
Robert
 
A

Al Bowers

herrcho said:
> #include <stdio.h>
>
> int main()
> {
> int i;
> char *p="sarang";
> for(i=0;i<4;i++)
> printf("%c",*(p+i));
> printf("\n");
> for(i=0;i<4;i++)
> printf("%c",p);
> printf(p);
> char *k=p;


Potential problems here.
> k[1]='u';
> printf("%s",p);
> }
>
> i compiled it with gcc, and it shows error message,
>
> i think the last 3 lines are problem.. Can anyone help me ?

What are the error messages? C99 will compile.
If you are using a C89 compiler then you will get an
error because the declaration of k is misplaced. ISO C89
does not allow mixed declarations.You will need to be
move the declaration up to the other declarations.

You have an additional problem that may cause the program to
crash. k will point to possibly read only memory. You
cannot safely assign to k[1].
Read faq question 1.32 located at:
http://www.eskimo.com/~scs/C-faq/q1.32.html
and change
char *p="sarang";
to
char p[] = "sarang";

/***************************/
#include <stdio.h>

int main(void)
{
int i;
char p[]="sarang";
char *k;

for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf("\n");
printf(p);
putchar('\n');
k=p;
k[1]='u';
printf("%s\n",p);
return 0;
}
 
R

Robert Stankowic

Capstar said:
Next time, try to include the error message so we can use it to
determine the problem.
#include <stdio.h>

int main()
{
int i;
char *p="sarang";
char *k;
for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf(p);
/*char *k=p;*/ k=p;

k[1]='u';
printf("%s",p);
}

i compiled it with gcc, and it shows error message,

i think the last 3 lines are problem.. Can anyone help me ?


This will compile with warnings, but won't run properly because of the
k[1]='u' line.
To solve this change
char *p="sarang";
in
char p[]="sarang";

The p[] version causes memory for "sarang" to be allocated on the stack.
Your version hard codes "sarang" in the .rodata section of your program,
which is not writable.


Let me rephrase that :)
The p[] version causes the compiler to reserve writeable memory in the
length of "sarang" + 1character for the trailing '\0' wherever it wants and
initializes it with the characters 's' 'a' 'r' 'a' 'n' 'g' '\0',
while the char *p version causes the compiler to put the unnamed string
"sarang", again wherever it wants, and assign the address of the first
character to p. The space where the literal lays may or may not be writeable
memory, that does not matter, you are simply _not allowed_ to write to it.
It may, if you are unlucky, work on your platform, but crash on another one.
Simply undefined behavior, everything may happen...

Robert
 
C

Capstar

Robert said:
The p[] version causes memory for "sarang" to be allocated on the stack.
Your version hard codes "sarang" in the .rodata section of your program,
which is not writable.


Let me rephrase that :)
The p[] version causes the compiler to reserve writeable memory in the
length of "sarang" + 1character for the trailing '\0' wherever it wants and
initializes it with the characters 's' 'a' 'r' 'a' 'n' 'g' '\0',
while the char *p version causes the compiler to put the unnamed string
"sarang", again wherever it wants, and assign the address of the first
character to p. The space where the literal lays may or may not be writeable
memory, that does not matter, you are simply _not allowed_ to write to it.
It may, if you are unlucky, work on your platform, but crash on another one.
Simply undefined behavior, everything may happen...

Robert

Thanks, I'm not very well in explaining things. But it never hurts to
try. :)
 
A

Al Bowers

Robert said:
p now points to the first character in a string literal, which is by
definition read only

Definition by what source?

If you read the faq question 1.32,
http://www.eskimo.com/~scs/C-faq/q1.32.html,
you will see that it says "possibly read only".

If you consult the Standards, you will see that the behavior is
undefined when you attempt to modify the array contents.

Of course the safe rule to follow, is to never attempt to modify the
array.
 
M

Martin Ambuhl

herrcho said:
#include <stdio.h>

int main()
{
int i;
char *p="sarang";

Change this to
char p[] = "sarang";
Your form makes p a pointer to a string literal.
My form makes it an array populated with a string.
for(i=0;i<4;i++)
printf("%c",*(p+i));
printf("\n");
for(i=0;i<4;i++)
printf("%c",p);
printf(p);
char *k=p;
k[1]='u';
printf("%s",p);


Make this
printf("%s\n",p);
Without a '\n' ending the last line of output, you are at the
mercy of the implementation and OS for what happens to that line.
It might never get written; it might be overwritten by the OS prompt;
it might have the OS prompt appended to its end; it might ...
 
P

pete

Al said:
Definition by what source?

If you read the faq question 1.32,
http://www.eskimo.com/~scs/C-faq/q1.32.html,
you will see that it says "possibly read only".

If you consult the Standards, you will see that the behavior is
undefined when you attempt to modify the array contents.

The nondistinction of identical string literals,
rather than read only memory, is the reason for undefined behavior,
which the standards emphasize, by juxtaposition.

C89 Last Draft
3.1.4 String literals
Semantics
"Identical string literals of either form need not be distinct.
If the program attempts to modify a string literal of either form,
the behavior is undefined."

N869
6.4.5 String literals
[#6] It is unspecified whether these arrays are distinct
provided their elements have the appropriate values. If the
program attempts to modify such an array, the behavior is
undefined.

J.5 Common extensions
J.5.5 Writable string literals
[#1] String literals are modifiable (in which case,
identical string literals should denote distinct objects).
 
R

Robert Stankowic

Al Bowers said:
Definition by what source?

If you read the faq question 1.32,
http://www.eskimo.com/~scs/C-faq/q1.32.html,
you will see that it says "possibly read only".

If you consult the Standards, you will see that the behavior is
undefined when you attempt to modify the array contents.

Of course the safe rule to follow, is to never attempt to modify the
array.

OK, bad wording on my side. With "by definition" I actually meant one cannot
write to it without causing UB, which I'd better mentioned explicitely.
Thank you for the correction.

Robert
 
A

Al Bowers

pete said:
Al Bowers wrote:



The nondistinction of identical string literals,
rather than read only memory, is the reason for undefined behavior,
which the standards emphasize, by juxtaposition.

"by Definition read only"?
Why would you take such a position? This declaration has
nothing to do with identical string literals. The standard clearly
states in 6.7.8.32 on initialization

" On the other hand, the declaration
char *p = "abc";
defines p with type ‘‘pointer to char’’ and initializes it to
point to an object with type ‘‘array of char’’ with length 4
whose elements are initialized with a character string literal.
If an attempt is made to use p to modify the contents of the
array, the behavior is undefined. "
^^^^^^^^^^^^^^^^^^


C89 Last Draft
3.1.4 String literals
Semantics
"Identical string literals of either form need not be distinct.
If the program attempts to modify a string literal of either form,
the behavior is undefined."

N869
6.4.5 String literals
[#6] It is unspecified whether these arrays are distinct
provided their elements have the appropriate values. If the
program attempts to modify such an array, the behavior is
undefined.

J.5 Common extensions
J.5.5 Writable string literals
[#1] String literals are modifiable (in which case,
identical string literals should denote distinct objects).

This is another issue which assures that it there is a common
extension of writable string literals then the implementation is
required to treat idential string literals as distinct objects.

If the implemention allows writable string literals then:
char *p1 = "Hello World";
char *p2 = "Hello World";

p1 and p2 points to seperate objects such that if you modify one
you will not modify the other.

If the implementation does not allow modification of string literals
then in the above declarations, p1 and p2 may point to the same object.

The point is there is no definition that requires read only string
literals. The implementation is free to make them read only or allow
modifications. Of course, from the point of view of writing portable
code, one should aways treat string literals as read only.
 
T

Thomas Stegen

Thanks, I'm not very well in explaining things. But it never hurts to
try. :)

From one perspective you were probably quite correct (I don't know though),
but from the comp.lang.c perspective there is nothing called .rodata and I
can
envision several architectures where such a section will not exist in the
compiled
code. What clc tries to do is to only give answers from the viewpoint of the
standard. Your explanation is a good example for why the standard disallows
writing to string literals, but you should specify that this sort of
explanation is
only valid for certain implementations. Just to clarify why Mr. S felt the
need
to rephrase you :)
 
C

Capstar

Thomas said:
From one perspective you were probably quite correct (I don't know though),
but from the comp.lang.c perspective there is nothing called .rodata and I
can
envision several architectures where such a section will not exist in the
compiled
code. What clc tries to do is to only give answers from the viewpoint of the
standard. Your explanation is a good example for why the standard disallows
writing to string literals, but you should specify that this sort of
explanation is
only valid for certain implementations. Just to clarify why Mr. S felt the
need
to rephrase you :)

I'll keep that in mind next time. ;)

Mark
 

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,079
Messages
2,570,574
Members
47,207
Latest member
HelenaCani

Latest Threads

Top