On Thu, 19 Nov 2009 13:08:33 -0800, Keith Thompson wrote:
[snipped and re-ordered for thematic reasons]
Passing a pointer-to-(non-const)-char to a function that takes a
pointer-to-const-char, as in "const_func(arg);" above, is perfectly
valid. The "const" on the parameter declaration is a promise not to use
the parameter to modify what the parameter points to. The code doesn't
try to violate that promise, so there's no problem.
Passing a pointer-to-const to a function that takes a
pointer-to-non-const, on the other hand, is a constraint violation. The
declaration "const char *const_arg;" promises not to use const_arg to
modify the data it points to. You can't pass that pointer to a function
that doesn't make a similar promise. But as we can see, you can modify
the same data through another path.
The above program should compile and run without error. If you change
"#if 0" to "#if 1", the compiler will complain.
I'm just about there with this material and this is certainly good source
to get right at the meat of it. This shows when the #ifs are changed:
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi3.c -o out
hi3.c: In function ‘const_func’:
hi3.c:13: error: assignment of read-only location ‘*param’
dan@dan-desktop:~/source$ cat hi3.c
#include <stdio.h>
void func(char *param)
{
*param = 'H';
puts(param);
}
void const_func(const char *param)
{
#if 1
*param = 'H'; /* illegal, violates "const" promise */
#endif
puts(param);
}
int main(void)
{
char s[] = "hello, world";
char *arg = s;
const char *const_arg = s;
func(arg); /* ok */
#if 0
func(const_arg); /* illegal, violates promise made by */
/* declaration of const_arg */
#endif
const_func(arg); /* ok, doesn't violate any "const" promise */
const_func(const_arg); /* ok */
return 0;
}
// gcc -std=c99 -Wall -Wextra hi3.c -o out
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi3.c -o out
hi3.c: In function ‘main’:
hi3.c:26: warning: passing argument 1 of ‘func’ discards qualifiers from
pointer target type
dan@dan-desktop:~/source$ cat hi3.c
#include <stdio.h>
void func(char *param)
{
*param = 'H';
puts(param);
}
void const_func(const char *param)
{
#if 0
*param = 'H'; /* illegal, violates "const" promise */
#endif
puts(param);
}
int main(void)
{
char s[] = "hello, world";
char *arg = s;
const char *const_arg = s;
func(arg); /* ok */
#if 1
func(const_arg); /* illegal, violates promise made by */
/* declaration of const_arg */
#endif
const_func(arg); /* ok, doesn't violate any "const" promise */
const_func(const_arg); /* ok */
return 0;
}
// gcc -std=c99 -Wall -Wextra hi3.c -o out
Let's look at a (perhaps) simpler example.
#include <stdio.h>
void func(char *param)
{
*param = 'H';
puts(param);
}
Why don't we see an H in stdout here?
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi4.c -o out
dan@dan-desktop:~/source$ ./out
here in func
Hello, world
Hello, world
Hello, world
dan@dan-desktop:~/source$ cat hi4.c
#include <stdio.h>
void func(char *param)
{
puts("here in func\n");
*param = 'H';
puts(param);
}
void const_func(const char *param)
{
#if 0
*param = 'H'; /* illegal, violates "const" promise */
#endif
puts(param);
}
int main(void)
{
char s[] = "hello, world";
char *arg = s;
const char *const_arg = s;
func(arg); /* ok */
#if 0
func(const_arg); /* illegal, violates promise made by */
/* declaration of const_arg */
#endif
const_func(arg); /* ok, doesn't violate any "const" promise */
const_func(const_arg); /* ok */
return 0;
}
// gcc -std=c99 -Wall -Wextra hi4.c -o out
dan@dan-desktop:~/source$