compilation warning with const parameter

S

subramanian

Consider the following program:

#include <stdio.h>

void myfn(const int **a)
{
static int i, j, k;

a[0] = &i;
a[1] = &j;
a[2] = &k;

return;
}

int main(void)
{
int *a[3];
int x, y, z;

a[0] = &x;
a[1] = &y;
a[2] = &z;

x = 10;
y = 20;
z = 30;

myfn(a);

return 0;
}

Suppose the program name is tmp.c

When this program is compiled with gcc under Redhat Enerprise Linux,
with the command
gcc -std=c99 tmp.c

the following Compilation warning is produced with gcc
const_ptr.c: In function `main':
const_ptr.c:27: warning: passing arg 1 of `myfn' from incompatible
pointer type

If I remove the const qualifier in myfn( ), the program compiles with
gcc without any warning.

However with VC++ 2005, there is no compilation warning with the
original program ie even when the const qualifier is present.

QUESTION:
 
W

Walter Roberson

Consider the following program:
#include <stdio.h>
void myfn(const int **a)
{

int main(void)
{
int *a[3];
myfn(a);

return 0;
}

the following Compilation warning is produced with gcc
const_ptr.c: In function `main':
const_ptr.c:27: warning: passing arg 1 of `myfn' from incompatible
pointer type
If I remove the const qualifier in myfn( ), the program compiles with
gcc without any warning.
Why is the warning generated with gcc ?

An array name mentioned outside of a & or sizeof construct decays
into a pointer to the first of its elements. It does -not- decay
into a const pointer to that element, and it does -not- const
qualify the elements of the array... not unless those elements
were declared const to begin with. The warning is thus correct:
you are passing something that is not declared const into a routine
that is expecting a const.

However with VC++ 2005, there is no compilation warning with the
original program ie even when the const qualifier is present.

Compilers are required to produce diagnostics if constraints
are violated, but whether those diagnostics are labeled as
"error" or "warning" or "note" or "Look At This!" is up to
the compiler.

A compiler is not required to stop compiling upon detecting something
interesting -- not unless it is an #error construct that is in full effect.

A compiler is allowed to produce any number of warnings or notes
that it wants, as long as it compiles code that does not violate
constaints.

The exact set of non-required diagnostics that a compiler produces
is a Quality of Implementation Issue (usually called QoI around here).
For the most part, compilers that produce valid diagnostics are
usually considered to be of higher quality than those which do not
bother to produce the diagnostic. We'll leave you to your own
conclusions as to what this implies about the relative worths
of gcc and VC++ 2005.
 
S

subramanian100in

An array name mentioned outside of a & or sizeof construct decays
into a pointer to the first of its elements. It does -not- decay
into a const pointer to that element, and it does -not- const
qualify the elements of the array... not unless those elements
were declared const to begin with. The warning is thus correct:
you are passing something that is not declared const into a routine
that is expecting a const.

If, that is the case, consider the following scenario:

char str[100];

temp_function(str);

void temp_function(const char*s)
{
/* do something */
}

In These kind of situations, gcc does not give any warning. Is this
scenario different from what you have stated above ?
 
W

Walter Roberson

An array name mentioned outside of a & or sizeof construct decays
into a pointer to the first of its elements. It does -not- decay
into a const pointer to that element, and it does -not- const
qualify the elements of the array... not unless those elements
were declared const to begin with. The warning is thus correct:
you are passing something that is not declared const into a routine
that is expecting a const.
[/QUOTE]
If, that is the case, consider the following scenario:
char str[100];
temp_function(str);

For the purposes of this discussion, I will assume that the
call to temp_function is coded is within some function, as
function calls cannot occur at file scope.
void temp_function(const char*s)
{
/* do something */
}
In These kind of situations, gcc does not give any warning. Is this
scenario different from what you have stated above ?

Your example does not make explicit whether the call to
temp_function occurs before any declaration or definition of
temp_function . If the call is indeed before the declaration or
definition, then Yes, it is a different case: you get into
implicit declarations without arguments and so on.

If you do have the declaration or definition before the call, then the
situation is indeed similar to what I described earlier and which has
been quoted above. Recall what I wrote earlier about
"Quality of Implementation" -- as there is no constraint violation,
no compiler is obliged to produce a diagnostic.
 
S

subramanian100in

Let me write the full code.

#include <stdio.h>


void test_fn(char *str1, const char *str2);

int main(void)
{
char str1[100] = "first string";
char str2[100] = "second string";

test_fn(str1, str2);

printf("%s", str1);

return 0;
}

void test_fn(char *str1, const char *str2)
{
while (*str1++ = *str2++)
;

return;
}


Here str2 was declared as an array in main() but received as const
char *. Here const is accepted by gcc. If const can be accepted here,
why not in "const char **a" which was given in the original program ?
 
B

Ben Bacarisse

subramanian said:
Consider the following program:

#include <stdio.h>

void myfn(const int **a)
{
}

int main(void)
{
int *a[3];
myfn(a);
return 0;
}
the following Compilation warning is produced with gcc
const_ptr.c: In function `main':
const_ptr.c:27: warning: passing arg 1 of `myfn' from incompatible
pointer type

If I remove the const qualifier in myfn( ), the program compiles with
gcc without any warning.

Later on in the thread you wonder why you don't get the same warning
when you pass a char * to a function expecting a const char *.

The reason is deeply buried in the standard. The upshot of which is
that argument passing is done with the same constraints as assignment
and section 6.5.16.1 includes the constraint that:

both operands are pointers to qualified or unqualified versions of
compatible types, and the type pointed to by the left has all the
qualifiers of the type pointed to by the right;

Now consider an assignment with types:

(const char *) = (char *)

the "type pointed to by the left" (const char) has all the qualifiers
of the "type pointed to by the right" (char). This is not true for
this pattern:

(const char **) = (char **)

because adding a const qualifier to the "type pointed to by the right"
is "char *const" not "const char *". This means, I think, that a
diagnostic is required.

The reason for these rules is outlined in the FAQ. It is so that
there is no way to obtain a pointer to a non-const version of a const
object without at least a warning.

I hope I have this right. It is a complex area and I don't want to
muddy the waters.
 
C

CBFalconer

.... snip ...

If, that is the case, consider the following scenario:

char str[100];

temp_function(str);

void temp_function(const char*s)
{
/* do something */
}

In These kind of situations, gcc does not give any warning. Is this
scenario different from what you have stated above ?

Assuming you didn't mean to define a prototype for temp_function,
but were positing a call to the properly protyped function you
listed, why should there be any warning? All the const in
prototype says is that temp_function will not modify the data
pointed at by str. The reverse is not so, i.e.:

const char str[100] = "something";

void tmp_func(char *s); /* a prototype */

...
tmp_func(str);

should generate a warning, because tmp_func is allowed to modify
the data passed to it.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 

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
473,781
Messages
2,569,616
Members
45,306
Latest member
TeddyWeath

Latest Threads

Top