a few doubts!

M

maadhuu

#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}


now, in TC there is absolutely no error .....i thought it
should........coz' when i declare a as a char * and assign it to some
string then it should be a constant and cannot do things like a[0] = '4'
and stuff........infact the entire thing here works properly....so why
should it work properly??
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
#include<stdio.h>
#include<conio.h>

conio.h is not a standard header. It's contents could be anything, and could
affect your program in ways we cannot determine

#include<string.h>
main()

main() takes either two arguments or none, and returns an int
you should use one of the two legal variants here, likely
int main(void)
{
char * a= "bcd";

a is declared as a pointer to an array of 4 char.
a can be altered
the array of 4 char cannot be altered
clrscr();

clrscr() is not a standard function. It's actions and side-effects could do
anything, and will affect your program in ways we cannot determine.
strcpy(a,"hello");

At least, undefined behaviour, because *a is only 4 char long, and the
side-effect (and function) of strcpy() would be to overwrite that space with a
6 char long value. 6 chars don't fit into a 4 char space.

The more knowledgable ones around here will tell you whether this is "illegal
behaviour" (because of the side-effect of strcpy(), which would be to attempt
to overwrite a char constant) or just "undefined behaviour".

a = "fgh";

Legal. You are not replacing the constant char array, you are replacing the
variable pointer.
a[0] = 't';

IIUC, this should be illegal.
printf("%s",a);

main() returns an int. return one here.
(Unless, your compiler is C99 compliant, in which case, the return value is
optional and defaults to a pre-determined value).
}


now, in TC there is absolutely no error .....i thought it
should........coz' when i declare a as a char * and assign it to some
string then it should be a constant and cannot do things like a[0] = '4'
and stuff........infact the entire thing here works properly....so why
should it work properly??


The compiler is non-compliant?
The compiler is broken?


- --
Lew Pitcher

Master Codewright & JOAT-in-training | GPG public key available on request
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFCc5PDagVFX4UWr64RAs8TAJ4p+ZyxVWzyLHSghtGc9yAdO9altQCgkxAZ
TDeV/fVJ3HZ6ZPh/iGDjvb8=
=jTH7
-----END PGP SIGNATURE-----
 
F

Flash Gordon

maadhuu said:
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}

now, in TC there is absolutely no error .....i thought it
should........coz' when i declare a as a char * and assign it to some
string then it should be a constant and cannot do things like a[0] = '4'
and stuff........infact the entire thing here works properly....so why
should it work properly??

It worked properly because it was neither an important demo with a large
sale hanging off it nor you showing it to your boss.

The standard says you are not allowed to write to a string literal, it
does not say it will generate an error or crash if you do.
 
O

osmium

maadhuu said:
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}


now, in TC there is absolutely no error .....i thought it
should........coz' when i declare a as a char * and assign it to some
string then it should be a constant and cannot do things like a[0] = '4'
and stuff........infact the entire thing here works properly....so why
should it work properly??

It would certainly be nicer if this didn't work, but I am not surprised that
it does. Only a language lawyer can determine whether your compiler breaks
some mandated rule, as opposed to simply letting some sloppy code through.

The fact that the strcpy works is especially troubling. I think part of the
venom against Schildt and his books is that he actually used to write
similar code on purpose. Probably not the strcpy with the too big aspect,
though.

FWIW it fails on DevC (mingw) and I would expect it to fail on most, if not
all, modern compilers. .
 
M

Mark McIntyre

the array of 4 char cannot be altered
yes

so this is undefined behaviour.
The more knowledgable ones around here will tell you whether this is "illegal
behaviour" (because of the side-effect of strcpy(), which would be to attempt
to overwrite a char constant) or just "undefined behaviour".

It is undefined. There's no syntax error here, so no reason to abort
compilation, if thats what you mean by 'illegal'.
a[0] = 't';

IIUC, this should be illegal.

Its undefined behaviour.
The compiler is non-compliant?

the warning levels are too low?
The compiler is broken?

The compiler is operating perfectly, but isn't obligated to produce a
diagnostic for careless programming.
 
E

Emmanuel Delahaye

maadhuu wrote on 30/04/05 :
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}

Crashy!

Get a better compiler an tunigs...

main.c:17: warning: return type defaults to `int'
main.c:17: warning: function declaration isn't a prototype
main.c: In function `main':
main.c:18: warning: initialization discards qualifiers from pointer
target type
main.c:21: warning: assignment discards qualifiers from pointer target
type main.c:24: warning: control reaches end of non-void function

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

"C is a sharp tool"
 
M

maadhuu

well, there is a 3rd way to pass arguments in main,which is environment
variables.....since u said there are only 2 or none.......
and i don't think this compiler is C-99 compliant.
 
E

Emmanuel Delahaye

(supersedes <[email protected]>)

maadhuu wrote on 30/04/05 :
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}

Crashy!

Get a better compiler and tunings...

main.c:17: warning: return type defaults to `int'
main.c:17: warning: function declaration isn't a prototype
main.c: In function `main':
main.c:18: warning: initialization discards qualifiers from pointer
target type
main.c:21: warning: assignment discards qualifiers from pointer target
type main.c:24: warning: control reaches end of non-void function

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

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
W

Walter Roberson

well, there is a 3rd way to pass arguments in main,which is environment
variables.....since u said there are only 2 or none.......

Passing an environment variable to main is a platform-specific
extension. The only *portable* choices are 2 arguments or no arguments.
 
E

Emmanuel Delahaye

(supersedes <[email protected]>)

Lew Pitcher wrote on 30/04/05 :
The compiler is non-compliant?
The compiler is broken?

None of this. The compiler is correct (KIM that the warnings are
optional) and the behaviour is undefined. The OP is unlucky because the
program doesn't crash.

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

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
E

Emmanuel Delahaye

S

SM Ryan

# #include<stdio.h>
# #include<conio.h>
# #include<string.h>
# main()
# {
# char * a= "bcd";
# clrscr();
# strcpy(a,"hello");
# a = "fgh";
# a[0] = 't';
# printf("%s",a);
# }

Some compilers allow strings to be overwritten by placing them in read-write memory
sometimes with the expectation the string can be modified. Writing outside an array
bounds does not necessarily trigger a fault action.

The code results are machine and compiler dependent.
 
K

Keith Thompson

SM Ryan said:
maadhuu said:
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}

Some compilers allow strings to be overwritten by placing them in
read-write memory sometimes with the expectation the string can be
modified. Writing outside an array bounds does not necessarily
trigger a fault action.

The code results are machine and compiler dependent.

[ Non-traditional '#' quoting character changed to '>'. ]
[ Excessively long lines reformatted. ]
[ Becoming seriously annoyed by gratuitously non-traditional formatting. ]

To be precise, an attempt to modify a string literal invokes undefined
behavior. An implementation is allowed to place string literals in a
read-only memory segment, causing a trap whenever the program attempts
to write to them. It's also allowed to place them in read-write
memory, and even to share the same memory for different occurrences of
the same string. For example, this:

#include <stdio.h>
#include <string.h>

int main(void)
{
char *s = "hello, world\n";
strcpy(s, "HAHA!\n");
printf("hello, world\n");
return 0;
}

could legally do any of the following:

Blow up on the strcpy() call (perhaps with a segmentation fault).
Print "hello, world".
Print "HAHA!".
Print "You have invoked undefined behavior and your mother wears army boots."
Make demons fly out your nose.

Some compilers may have an an option to control whether string
literals are stored in read-only or read-write memory. Such an option
is useful mostly to diagnose this kind of problem (or, if you're
desparate, to work around it). The only real solution is to avoid
writing to string literals in the first place.

One oddity is that, for historical reasons, a string literal is not
treated as "const". If it were, the compiler would be required to
diagnose most cases of this error.
 
W

Walter Roberson

To be precise, an attempt to modify a string literal invokes undefined
behavior.
For example, this:
could legally do any of the following:
Blow up on the strcpy() call (perhaps with a segmentation fault).
Make demons fly out your nose.
Some compilers may have an an option to control whether string
literals are stored in read-only or read-write memory.

When is gcc getting a --no-nosedemons option ?
 
C

CBFalconer

Keith said:
.... snip ...

One oddity is that, for historical reasons, a string literal is not
treated as "const". If it were, the compiler would be required to
diagnose most cases of this error.

However, at least with gcc, you can get that effect by using
-Wwrite-strings. So some of us can protect against such
non-standard usage. (This is after -W -Wall -ansi -pedantic).
 
B

Barry Schwarz

# #include<stdio.h>
# #include<conio.h>
# #include<string.h>
# main()
# {
# char * a= "bcd";
# clrscr();
# strcpy(a,"hello");
# a = "fgh";
# a[0] = 't';
# printf("%s",a);
# }

Some compilers allow strings to be overwritten by placing them in read-write memory
sometimes with the expectation the string can be modified. Writing outside an array
bounds does not necessarily trigger a fault action.

The code results are machine and compiler dependent.

All undefined behavior is compiler and machine dependent. That it no
way lessens the undefined nature of the behavior. Both actions,
modifying a string literal and writing outside an array specifically
are prohibited.


<<Remove the del for email>>
 
K

Keith Thompson

CBFalconer said:
However, at least with gcc, you can get that effect by using
-Wwrite-strings. So some of us can protect against such
non-standard usage. (This is after -W -Wall -ansi -pedantic).

The problem with that is that it can cause spurious warnings if you
haven't been careful about using "const" whenever it's appropriate.
For example:

#include <stdio.h>

void foo(char *s)
{
printf("s = \"%s\"\n", s);
}

int main(void)
{
foo("hello");
return 0;
}

If strings are treated as const, this will cause a warning on the call
to foo() -- and there's undoubtedly a lot of code with this kind of
problem.

Of course, since foo() doesn't modify its argument (or what it points
to), it would make sense to declare the parameter as "const char *s"
anyway.
 
J

Jack Klein

maadhuu said:
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}


now, in TC there is absolutely no error .....i thought it
should........coz' when i declare a as a char * and assign it to some
string then it should be a constant and cannot do things like a[0] = '4'
and stuff........infact the entire thing here works properly....so why
should it work properly??

It would certainly be nicer if this didn't work, but I am not surprised that
it does. Only a language lawyer can determine whether your compiler breaks
some mandated rule, as opposed to simply letting some sloppy code through.

The fact that the strcpy works is especially troubling. I think part of the
venom against Schildt and his books is that he actually used to write
similar code on purpose. Probably not the strcpy with the too big aspect,
though.

FWIW it fails on DevC (mingw) and I would expect it to fail on most, if not
all, modern compilers. .

The reason that it does not fail here is not the age of the compiler,
it is the platform provided by the underlying operating system, which
did not have memory management hardware.
 
J

Jack Klein

maadhuu wrote on 30/04/05 :
#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char * a= "bcd";
clrscr();
strcpy(a,"hello");
a = "fgh";
a[0] = 't';
printf("%s",a);
}

Crashy!

Get a better compiler an tunigs...

main.c:17: warning: return type defaults to `int'
main.c:17: warning: function declaration isn't a prototype
main.c: In function `main':
main.c:18: warning: initialization discards qualifiers from pointer
target type
main.c:21: warning: assignment discards qualifiers from pointer target
type main.c:24: warning: control reaches end of non-void function

Perhaps you're the one who needs to get a better compiler? I see two
concerns:

1. It issues diagnostics for lines 17 through 24 from source that
only has 12 lines.

2. FAR MORE IMPORTANTLY, it issues two "warning" messages that are
JUST PLAIN FLAT OUT WRONG (or are you compiling with a C++ compiler?).

The warning messages for lines 18 and 21 state "discards qualifiers
from pointer target type". NO, THESE LINES DO NOT. The type of the
string literals "bcd" and "fgh" are array of char, and most
specifically not array of const char.

So what C compiler did you use that produced this incorrect messages?
 

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,163
Messages
2,570,897
Members
47,434
Latest member
TobiasLoan

Latest Threads

Top