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

Annoying const problem

P: n/a
I have a function that always takes 16 bytes of data and doesn't modify
it:

void func( byte const (*data)[16] );

However, if I try to call it with non-const data, the compiler is
unable to perform the conversion:

static const byte bar1[16] = { 0 };

int foo()
{
byte bar2[16] = { 0 };

func( &bar1 ); /* OK */
func( &bar2 ); /* Error */
}

Is there any work-around to this, other than defining a const and a
nonconst version of func, or passing a pointer to the first element
of data and thereby losing the compile-time length check?

Dec 10 '06 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Old Wolf wrote:
>
I have a function that always takes 16 bytes of data and doesn't
modify it:

void func( byte const (*data)[16] );

However, if I try to call it with non-const data, the compiler is
unable to perform the conversion:

static const byte bar1[16] = { 0 };

int foo()
{
byte bar2[16] = { 0 };

func( &bar1 ); /* OK */
func( &bar2 ); /* Error */
}

Is there any work-around to this, other than defining a const and a
nonconst version of func, or passing a pointer to the first element
of data and thereby losing the compile-time length check?
Probably it will be enough to compile with a C compiler. Looks
like you are using C++.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Dec 10 '06 #2

P: n/a
In article <11**********************@n67g2000cwd.googlegroups .com>,
Old Wolf <ol*****@inspire.net.nzwrote:
>void func( byte const (*data)[16] );
[Presumably byte is typedefed.]
>However, if I try to call it with non-const data, the compiler is
unable to perform the conversion:
You'll have to put in an explicit cast:

func( (byte const (*)[16]) &bar2 );

Of course, this loses the type checking, but only for the cases where
you cast it.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 10 '06 #3

P: n/a
CBFalconer wrote:
Old Wolf wrote:
void func( byte const (*data)[16] );
static const byte bar1[16] = { 0 };

int foo()
{
byte bar2[16] = { 0 };

func( &bar1 ); /* OK */
func( &bar2 ); /* Error */
}

Probably it will be enough to compile with a C compiler. Looks
like you are using C++.
Actually I'm not. Thanks for guessing though. What C compiler are
you using that compiles this code without issuing a diagnostic?

typedef unsigned char byte;
void func( byte const (*data)[16] ) {}
int main()
{
byte bar[16] = { 0 };
func( &bar );
}

Dec 11 '06 #4

P: n/a
Old Wolf wrote:
I have a function that always takes 16 bytes of data and doesn't modify
it:

void func( byte const (*data)[16] );

However, if I try to call it with non-const data, the compiler is
unable to perform the conversion:

static const byte bar1[16] = { 0 };

int foo()
{
byte bar2[16] = { 0 };

func( &bar1 ); /* OK */
func( &bar2 ); /* Error */
}

Is there any work-around to this, other than defining a const and a
nonconst version of func, or passing a pointer to the first element
of data and thereby losing the compile-time length check?
I think not. The non-const version can, of course, be a wrapper for the
const version.

--
Thad
Dec 11 '06 #5

P: n/a
Old Wolf wrote:
CBFalconer wrote:
Old Wolf wrote:
void func( byte const (*data)[16] );
static const byte bar1[16] = { 0 };
>
int foo()
{
byte bar2[16] = { 0 };
>
func( &bar1 ); /* OK */
func( &bar2 ); /* Error */
}
Probably it will be enough to compile with a C compiler. Looks
like you are using C++.

Actually I'm not. Thanks for guessing though. What C compiler are
you using that compiles this code without issuing a diagnostic?

typedef unsigned char byte;
void func( byte const (*data)[16] ) {}
int main()
{
byte bar[16] = { 0 };
func( &bar );
}
The tendra compiler accepts it without a diagnostic. With extra
warnings enabled, it still only warns about an unused variable "data".
Of course, considering gcc, icc and comeau (online) all report an
error, I would not be surprised if it is a bug.

Dec 11 '06 #6

P: n/a
Old Wolf said:
I have a function that always takes 16 bytes of data and doesn't modify
it:

void func( byte const (*data)[16] );

However, if I try to call it with non-const data, the compiler is
unable to perform the conversion:

static const byte bar1[16] = { 0 };

int foo()
{
byte bar2[16] = { 0 };

func( &bar1 ); /* OK */
func( &bar2 ); /* Error */
}
Please produce the smallest *compilable* program (in the sense that it would
compile if not for your func(&bar2) call) that reproduces the problem.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 11 '06 #7

P: n/a
Richard Heathfield wrote:
Old Wolf said:
I have a function that always takes 16 bytes of data and doesn't modify
it:
However, if I try to call it with non-const data, the compiler is
unable to perform the conversion:
Please produce the smallest *compilable* program (in the sense that it would
compile if not for your func(&bar2) call) that reproduces the problem.
See my response to CBF else-thread

Dec 11 '06 #8

P: n/a
Old Wolf said:

<snip>
typedef unsigned char byte;
void func( byte const (*data)[16] ) {}
int main()
{
byte bar[16] = { 0 };
func( &bar );
}
I hate questions like this, and I'm not going to try to explain it, but
FWIW:

typedef unsigned char byte;
void func( byte (* const data)[16] ) {} /* observe the difference here */
int main()
{
byte bar[16] = { 0 };
func( &bar );
return 0;
}

compiles cleanly (modulo one utterly irrelevant warning) under gcc, using
moderately strict flags (-W -Wall -ansi -pedantic).

So it seems to me that, once more, we are staring at C's recondite handling
of pointers to const data (as opposed to const pointers to data), the logic
of which I understood for about 20 minutes back in 2001, and promptly
forgot again.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 11 '06 #9

P: n/a
In article <11*********************@n67g2000cwd.googlegroups. com>,
Old Wolf <ol*****@inspire.net.nzwrote:
>See my response to CBF else-thread
Since this thread has not yet included a (natural) language flame, I
would point out that "else-thread" should not mean what you want it to
mean. By analogy with "elsewhere", which means "somewhere else", it
should mean "somethread else" - that is, in a different thread.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 11 '06 #10

P: n/a
Richard Heathfield wrote:
Old Wolf said:
typedef unsigned char byte;
void func( byte const (*data)[16] ) {}
int main()
{
byte bar[16] = { 0 };
func( &bar );
}

I hate questions like this, and I'm not going to try to explain it, but
FWIW:

typedef unsigned char byte;
void func( byte (* const data)[16] ) {} /* observe the difference here */
int main()
{
byte bar[16] = { 0 };
func( &bar );
return 0;
}

compiles cleanly (modulo one utterly irrelevant warning) under gcc, using
moderately strict flags (-W -Wall -ansi -pedantic).
This is a top-level const, which is only relevant within func,
it does not affect what you can pass to it. So this version does
not allow:

byte const baz[16] = { 0 };
func(&baz);

which was part of my original problem and I should have included
it in the above sample code.
So it seems to me that, once more, we are staring at C's
recondite handling of pointers to const data (as opposed
to const pointers to data), the logic of which I understood
for about 20 minutes back in 2001, and promptly forgot again.
The above code seems to demonstrate that an array of objects,
each of which is const, is somehow different to a const array of
objects, each of which is not const.

If you understood this, then you understood it for 20 minutes
more than I did :)

FWIW the code compiles successfully in C++.

Dec 11 '06 #11

P: n/a
In article <11**********************@80g2000cwy.googlegroups. com>
Old Wolf <ol*****@inspire.net.nzwrote:
["const" problem illustrations snipped]
>FWIW the code compiles successfully in C++.
Sadly, the "const" rules in C are just broken. (The C++ rules
work. They do, however, pretty much need a lot of the rest of the
C++ machinery -- such as function overloading -- to work consistently.
C could have used the C++ rules, but the result would still be less
secure than the C++ rules, due to functions like strchr() removing
"const" qualifiers [in C].)

My preferred solution is to omit "const" as much as possible in C
code, but I recognize that not everyone favors this approach. :-)

I also wish that, in lieu of the C folks using "correct" rules
a la C++, they had simply made "const" a storage modifier rather
than a "type qualifier". In this case, "const" would have meant
"put this object into read-only memory if possible", but would have
had no effect at all on its type. Many argue that this would lose
some type-safety, but given, e.g.:

const char *qual;
...
char *unqual = strchr(unqual, *unqual);

we already get C code that quietly removes "const", so I think this
"some" type-safety is "very little" type-safety, and not worth its
cost.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Dec 12 '06 #12

P: n/a
In article <el*********@news1.newsguy.comI wrote, in part:
const char *qual;
...
char *unqual = strchr(unqual, *unqual);
Gah. This call is, of course, supposed to read:

char *unqual = strchr(qual, *qual);
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Dec 12 '06 #13

P: n/a
On Tue, 12 Dec 2006 06:53:45 +0000, Chris Torek wrote:
In article <el*********@news1.newsguy.comI wrote, in part:
> const char *qual;
...
char *unqual = strchr(unqual, *unqual);

Gah. This call is, of course, supposed to read:

char *unqual = strchr(qual, *qual);
strchr()/strrchr() is a big wart (but then so is all of string.h, IMO).

However it is possible/easy/better to have a string API that doesn't
return a pointer to offsets within itself (and if you insist on
using string.h then strspn/strcspn can easily be used).
And non-string APIs tend to not even consider design decisions like that.
So, while const does have it's problems (see earlier in this thread),
using a (const Foo *foo) parameter in a function provides great
documentation and is worth using.

--
James Antill -- ja***@and.org
http://www.and.org/and-httpd/ -- $2,000 security guarantee
http://www.and.org/vstr/
Dec 12 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.