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

compilation warning with const parameter

P: n/a
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:
-----------------
Why is the warning generated with gcc ?

---------------------------------------------------
su**************@yahoo.com
India

Feb 19 '07 #1
Share this Question
Share on Google+
6 Replies


P: n/a
In article <11**********************@m58g2000cwm.googlegroups .com>,
subramanian <su**************@yahoo.comwrote:
>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.
--
Is there any thing whereof it may be said, See, this is new? It hath
been already of old time, which was before us. -- Ecclesiastes
Feb 19 '07 #2

P: n/a
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 ?

Feb 19 '07 #3

P: n/a
In article <11*********************@j27g2000cwj.googlegroups. com>,
su**************@yahoo.com, India <su**************@yahoo.comwrote:
>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);
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.
--
I was very young in those days, but I was also rather dim.
-- Christopher Priest
Feb 19 '07 #4

P: n/a
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 ?

Feb 19 '07 #5

P: n/a
"subramanian" <su**************@yahoo.comwrites:
Consider the following program:

#include <stdio.h>

void myfn(const int **a)
{
<snip>
}

int main(void)
{
int *a[3];
<snip>
myfn(a);
return 0;
}
<snip>
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.

--
Ben.
Feb 19 '07 #6

P: n/a
"su**************@yahoo.com, India" wrote:
>
.... 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
Feb 20 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.