473,385 Members | 1,588 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Whats the deal with 'const'?

Whats the point of making functions which take arguments of a form like
"const char *x"? It appears that this has no effect on the function
actually working and doing its job, ie, if the function doesn't write
to x, then it doesnt seem like the compiler could care less whether I
specify the const part. Quite the opposite, if one uses const
liberally and then later goes back and changes the functions, headaches
will inevitably occur as one tries to compile and the compiler gripes
because now suddenly you ARE writing to x, so you have to go back and
remove the const keyword, and this might mean painstakingly removing it
from dozens of lines if the function in question is deeply nested
amidst a family of functions that call eachother and all have 'const'
keywords.

Is const, in this context (ie passing const arguments to functions)....

1. A Java-like "babysitter" keyword based on the premise that all
programmers are idiots and must have their hands held at all times?
2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?
3. About as useful as a comment, with no other purpose but as a little
yellow sticky note saying "this function should act nondestructively on
this particular thing"?

I always assumed it was some combination of 1 and 3 and so I tend to
never, ever use the thing...

Thanks, this is something I've always been curious about =)

Snis Pilbor

Jul 15 '06 #1
20 2404
Snis Pilbor posted:
Whats the point of making functions which take arguments of a form like
"const char *x"?

(Just for sake of pedantry:)

This is a non-const pointer variable which points to a const char.

It appears that this has no effect on the function
actually working and doing its job, ie, if the function doesn't write
to x, then it doesnt seem like the compiler could care less whether I
specify the const part.

The calling function cares:
void Func(char*);

int main(void)
{
char const c = 0;

Func(&c); /* Compiler ERROR */
}

Quite the opposite, if one uses const
liberally and then later goes back and changes the functions, headaches
will inevitably occur as one tries to compile and the compiler gripes
because now suddenly you ARE writing to x, so you have to go back and
remove the const keyword, and this might mean painstakingly removing it
from dozens of lines if the function in question is deeply nested
amidst a family of functions that call eachother and all have 'const'
keywords.

Revising whether a function alters its argument changes the very nature of
the function!

I take it you're new to "const"? "const" is brilliant.

Use it (almost) everywhere you can and you'll be left with very robust
code.

1. A Java-like "babysitter" keyword based on the premise that all
programmers are idiots and must have their hands held at all times?

I would consider "const" to have two main purposes:

(1) To aid in optimisation.
(2) To make code fail to compile if "constness" is violated.
<OFF-TOPIC>

Using function overloading in C++, you can write two totally different
functions -- one which alters its argument, and one which doesn't:

void Func(int *p);

void Func(int const *p);

</OFF-TOPIC>

2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?

Consider:

int Func(int const x)
{
return x + 5;
}

Maybe the compiler will re-use the argument variable... ?

3. About as useful as a comment, with no other purpose but as a little
yellow sticky note saying "this function should act nondestructively on
this particular thing"?

It is reliable as such an indicator.
Don't forget:

It's undefined behaviour to alter a const object.
--

Frederick Gotham
Jul 15 '06 #2
It helps with debugging. Putting const in the prototype allows you to 1)
send a "const" variable to the function or a nonconst variable to the
function. Without the const keyword, you could only send a nonconst variable
to the function. 2) when using references and pointers, it prevents the
function from modifying it which allows you to isolate bugs.

Although I believe references have to do with cpp, here is something that
you might find useful. Take this definition for example:

void object::func( const int* const variable ) const { ; }

the first const prevents the pointer from be moved around ( pointer
arithmetic ), the second const prevents the data to which the pointer points
to from being manipulated, and the third const prevents the function from
modifying member variables that belong to the class "object". The third one
is a cpp feature, but the other two should still hold true for C. Although I
believe the keyword "const" is a cpp keyword anyways and not a C keyword.
There is some ambituity there too I believe but I'm not sure.

I doubt there is any optimization, I don't know exactly what the compiler
produces when it comes to the const keyword so I don't know.

"Snis Pilbor" <sn********@yahoo.comwrote in message
news:11**********************@35g2000cwc.googlegro ups.com...
Whats the point of making functions which take arguments of a form like
"const char *x"? It appears that this has no effect on the function
actually working and doing its job, ie, if the function doesn't write
to x, then it doesnt seem like the compiler could care less whether I
specify the const part. Quite the opposite, if one uses const
liberally and then later goes back and changes the functions, headaches
will inevitably occur as one tries to compile and the compiler gripes
because now suddenly you ARE writing to x, so you have to go back and
remove the const keyword, and this might mean painstakingly removing it
from dozens of lines if the function in question is deeply nested
amidst a family of functions that call eachother and all have 'const'
keywords.

Is const, in this context (ie passing const arguments to functions)....

1. A Java-like "babysitter" keyword based on the premise that all
programmers are idiots and must have their hands held at all times?
2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?
3. About as useful as a comment, with no other purpose but as a little
yellow sticky note saying "this function should act nondestructively on
this particular thing"?

I always assumed it was some combination of 1 and 3 and so I tend to
never, ever use the thing...

Thanks, this is something I've always been curious about =)

Snis Pilbor

Jul 15 '06 #3
aragonsr posted:

void object::func( const int* const variable ) const { ; }

the first const prevents the pointer from be moved around ( pointer
arithmetic ),

The first const prevents alteration of the data which is pointed to.

the second const prevents the data to which the pointer
points to from being manipulated,

The second const prevents alteration of the pointer variable itself.

I doubt there is any optimization, I don't know exactly what the
compiler produces when it comes to the const keyword so I don't know.

It's very likely to change:

unsigned const len = 5;

unsigned i = len;
into simply:
unsigned i = 5;
This would have an optimising effect on the resultant machine code, as,
rather than accessing "len" and subsequently loading a register with its
value, it would use a CPU instruction whereby it can pass 5 directly.
--

Frederick Gotham
Jul 15 '06 #4
On 15 Jul 2006 09:34:40 -0700, "Snis Pilbor" <sn********@yahoo.com>
wrote in comp.lang.c:
Whats the point of making functions which take arguments of a form like
"const char *x"? It appears that this has no effect on the function
actually working and doing its job, ie, if the function doesn't write
to x, then it doesnt seem like the compiler could care less whether I
specify the const part. Quite the opposite, if one uses const
liberally and then later goes back and changes the functions, headaches
will inevitably occur as one tries to compile and the compiler gripes
because now suddenly you ARE writing to x, so you have to go back and
remove the const keyword, and this might mean painstakingly removing it
from dozens of lines if the function in question is deeply nested
amidst a family of functions that call eachother and all have 'const'
keywords.
The definition of a function parameter as "const char *x" defines that
argument as a pointer to one or more constant characters. The pointer
may be changed, any characters that it points to may not. This means
it may be called with a pointer to constant or non constant
characters. It is also a promise by the implementer of the function
that it will not attempt to modify any character(s) pointed to by 'x'.

Given a prototype of a function that accepts a pointer to const char,
a programmer may call that function with a pointer to one or more
chars that may not be modified, either an actual constant char or
array of constant chars, or a string literal.

Or it may be that the data pointed to is not a literal or constant,
but the caller needs it to keep its present value for further
processing.
Is const, in this context (ie passing const arguments to functions)....

1. A Java-like "babysitter" keyword based on the premise that all
programmers are idiots and must have their hands held at all times?
Making an object parameter constant is something like babysitting.
Some pedants here seem to like it, but it is only for the use of the
programmer writing the function. Example:

int some_func(const int x)
{
/* body */
}

The programmer is expressing his intent not to change the value of the
int parameter 'x' inside the function, and is instructing the compiler
to warn him if he does so. It is not part of the function's
interface, and completely useless information to a caller of the
function, because the 'x' the function receives is a copy of the
caller's value, and changes made to it inside this function cannot
have any effect on any object in the caller.

Some people like this because it prevents a certain type of error,
namely when an argument is modified early in a function when code
later in a function expects it to retain the original value.

My response to that would be that if a function is long or complex
enough that such a mistake is easy to make and easy to overlook, the
function should be split into two or more smaller, simpler functions.
2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?
The C standard does not define optimizations. There might well be
optimizations possible with data pointed to by a pointer to const, but
that is an implementation detail and off-topic here.
3. About as useful as a comment, with no other purpose but as a little
yellow sticky note saying "this function should act nondestructively on
this particular thing"?
No, it is far, far more useful than a comment, at least when talking
about pointers to const objects. Especially when used properly.
I always assumed it was some combination of 1 and 3 and so I tend to
never, ever use the thing...

Thanks, this is something I've always been curious about =)
Consider:

int my_strlen1(const char *x)
{
int count = 0;
while (*x)
{
++count;
++x;
}
return count;
}

int my_strlen2(char *x)
{
int count = 0;
while (*x)
{
++count;
++x;
}
return count;
}

int main(void)
{
const char *str = "Hello, World!";
int l1 = my_strlen1(str);
int l2 = my_strlen2(str);
puts(str);
return 0;
}

Your compiler should issue a diagnostic when you attempt to call
my_strlen2 with a pointer to const. And that's important, because the
pointer 'str' points to a string literal, and modifying a string
literal produces undefined behavior.

If you modify my_strlen1, say like this:

int my_strlen1(const char *x)
{
int count = 0;
while (*x)
{
++count;
*x = '?';
++x;
}
return count;
}

....the compiler will issue a diagnostic. To remove the diagnostic you
must remove the const qualifier. If your code is organized properly,
that is the same prototype is in scope at the definition and all calls
to a function, removing the const qualifier from the prototype will
cause a diagnostic when the caller sends a pointer to a string literal
to the function. And this is a good thing, because passing a string
literal to a function that attempts to modify it is a serious error
and causes undefined behavior.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 15 '06 #5

Frederick Gotham wrote:
Snis Pilbor posted:
(snip)
Quite the opposite, if one uses const
liberally and then later goes back and changes the functions, headaches
will inevitably occur as one tries to compile and the compiler gripes
because now suddenly you ARE writing to x, so you have to go back and
remove the const keyword, and this might mean painstakingly removing it
from dozens of lines if the function in question is deeply nested
amidst a family of functions that call eachother and all have 'const'
keywords.


Revising whether a function alters its argument changes the very nature of
the function!
(snip)
Not to be argumentative, but consider the following two versions of the
same function:

void print_first_5( char *x )
{
char buf[6];
int i;

for ( i = 0; i < 5; i++ )
buf[i] = x[i];

buf[5] = '\0';
printf( buf );
}

void print_first_5( char *x )
{
char tmp;

tmp = x[5];
x[5] = '\0';
printf( x );
x[5] = tmp;
}

As far as I can tell, the 2nd is both faster and takes less memory.
The two do the exact same thing, assuming that printf itself acts
nondestructively. If I used const to tell the compiler that
print_first_5 acts nondestructively on x in the 2nd version, the
compiler would think I was mistaken even though I'm correct. The point
is, the change can hardly be said to "change the very nature of this
function", and if this were deeply nested in a family of functions
using const arguments, a massive headache would arise.

S.P.

Jul 15 '06 #6
Jack Klein posted:

>2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?

The C standard does not define optimizations. There might well be
optimizations possible with data pointed to by a pointer to const, but
that is an implementation detail and off-topic here.

Yes, that must be the exact reason why we have a "register" keyword.

I suppose "inline" has nothing to do with optimisation either.
--

Frederick Gotham
Jul 15 '06 #7
Snis Pilbor posted:
Not to be argumentative, but consider the following two versions of the
same function:

void print_first_5( char *x )
{
char buf[6];
int i;

for ( i = 0; i < 5; i++ )
buf[i] = x[i];

buf[5] = '\0';
printf( buf );
}

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

void PrintFirst5(char const *p)
{
char static buf[5+1]; /* Auto null terminator */

memcpy(buf,p,5);

puts(buf);
}

void print_first_5( char *x )
{
char tmp;

tmp = x[5];
x[5] = '\0';
printf( x );
x[5] = tmp;
}

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

void PrintFirst5(char *p)
{
char * const register p_last = p + 5;

char const tmp = *p_last;

*p_last = 0;

puts(p);

*p_last = tmp;
}

As far as I can tell, the 2nd is both faster and takes less memory.

Indeed, however the array which it accesses must be non-const.

Consider:

PrintFirst5("carpenter");

If I used const to tell the compiler that
print_first_5 acts nondestructively on x in the 2nd version, the
compiler would think I was mistaken even though I'm correct.

You are mistaken.

You alter the data. Just because you later restore it to its original state
doesn't mean there was no alteration in the first place.

By your logic, if I was caught shoplifting, I could say "I was only
borrowing it, and was going to restore it to its original position before
anyone noticed".

The point is, the change can hardly be said to "change the very nature
of this function", and if this were deeply nested in a family of
functions using const arguments, a massive headache would arise.

The second form of the function is "clever".

You have changed the way the function works.

Perhaps the most fundamental aspect of a function, and the aspect which
should be documented clearly, is "whether it alters its arguments".

<OFF-TOPIC>

In C++, you could get the best of both worlds by using function overloading
to supply two functions: one which can work with const data, and one which
is optimised to work with non-const data.

</OFF-TOPIC>
Get the hang of using "const" and you'll realise it's the best thing since
sliced bread.
--

Frederick Gotham
Jul 15 '06 #8
Frederick Gotham posted:

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

void PrintFirst5(char const *p)
{
char static buf[5+1]; /* Auto null terminator */

memcpy(buf,p,5);

puts(buf);
}

I should have written the function parameter as:

char const * const p
void PrintFirst5(char *p)
{
char * const register p_last = p + 5;

char const tmp = *p_last;

*p_last = 0;

puts(p);

*p_last = tmp;
}

I should have written the function parameter as:

char * const p

--

Frederick Gotham
Jul 15 '06 #9
Jack Klein wrote:
>
int my_strlen1(const char *x)
{
int count = 0;
while (*x)
{
++count;
++x;
}
return count;
}

int my_strlen2(char *x)
{
int count = 0;
while (*x)
{
++count;
++x;
}
return count;
}

int main(void)
{
const char *str = "Hello, World!";
int l1 = my_strlen1(str);
int l2 = my_strlen2(str);
puts(str);
return 0;
}
Current compilers exhibit a wide variety of behaviors in this situation.
Even within the same compiler family, one compiler may not have any
diagnostic available, and will link and run without problem, and another
may fail, particularly if the C code is compiled under C++.
I filed a problem report against a compiler for linux x86-64 which has
no available diagnostic or failure mode, while its Windows x64 sibling
runs into trouble later in the compilation.
With gcc 4.2, I saw a change in behavior between -m64 and -m32, where
the original problem is diagnosed directly only in -m64 mode, and the
consequences depend on context (even though the string is never
re-written). This contributed to my difficulty in convincing a bug
report team of the desirability of the diagnostic.
The f2c translator, even in "ansi" mode, generates legacy style code
which passes string constants without using "const" in the prototypes,
and that has only recently begun to fail.
Jul 15 '06 #10
REH

"Snis Pilbor" <sn********@yahoo.comwrote in message
news:11**********************@i42g2000cwa.googlegr oups.com...
>
Not to be argumentative, but consider the following two versions of the
same function:

void print_first_5( char *x )
{
char buf[6];
int i;

for ( i = 0; i < 5; i++ )
buf[i] = x[i];

buf[5] = '\0';
printf( buf );
}

void print_first_5( char *x )
{
char tmp;

tmp = x[5];
x[5] = '\0';
printf( x );
x[5] = tmp;
}

As far as I can tell, the 2nd is both faster and takes less memory.
The two do the exact same thing, assuming that printf itself acts
nondestructively. If I used const to tell the compiler that
print_first_5 acts nondestructively on x in the 2nd version, the
compiler would think I was mistaken even though I'm correct. The point
is, the change can hardly be said to "change the very nature of this
function", and if this were deeply nested in a family of functions
using const arguments, a massive headache would arise.
First, I would output the characters directly and not copy them, nor modify
the original array. Secondly, the convenience and safety of not
unnecessarily modifying the input parameter outweighs any performance you
think you are losing. Unless it is a real issue (and since you are writing
to output, I seriously doubt it), don't worry so much about which is
"faster." By not modifying the string, the function can be used with both
modifiable and non-modifiable strings, and in this case, that probably
better than any perceived loss in speed.
REH
Jul 15 '06 #11
Frederick Gotham wrote:
Jack Klein posted:

>>2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?
The C standard does not define optimizations. There might well be
optimizations possible with data pointed to by a pointer to const, but
that is an implementation detail and off-topic here.


Yes, that must be the exact reason why we have a "register" keyword.

I suppose "inline" has nothing to do with optimisation either.

Your sarcasm is misplaced; optimization is indeed not the primary intent of
"const". By that reasoning you might call static typing an optimization. It
may allow optimization, but that's not its primary benefit.

Moreover, the standard really *doesn't* define optimizations, it merely
standardizes certain hints to the compiler (which is free to ignore them).
I've seen plenty of compilers that all but ignore the "register" keyword,
for example, because they can do a far better job of register allocation
than any human programmer could (especially across different platforms). The
"register" keyword is a holdover from less sophisticated times.

Compilers that support "inline" tend to respect it (and some even have a
corresponding "noinline" keyword), since determining what functions to
inline is not something that compilers are perfect at yet (and may never
become, since in many cases profiling is required).

The mere fact that the standard gives these optimization hints uniform names
and guarantees that programs can use them should not be taken as an
indication that the standard is in the business of telling implementations
how to optimize. In fact, that would be anathema to the C philosophy of
leaving things unsaid that don't need to be said.

S.
Jul 15 '06 #12
Snis Pilbor wrote:
Frederick Gotham wrote:
>>Snis Pilbor posted:
(snip)

>>>Quite the opposite, if one uses const
liberally and then later goes back and changes the functions, headaches
will inevitably occur as one tries to compile and the compiler gripes
because now suddenly you ARE writing to x, so you have to go back and
remove the const keyword, and this might mean painstakingly removing it
from dozens of lines if the function in question is deeply nested
amidst a family of functions that call eachother and all have 'const'
keywords.


Revising whether a function alters its argument changes the very nature of
the function!
(snip)


Not to be argumentative, but consider the following two versions of the
same function:

void print_first_5( char *x )
{
char buf[6];
int i;

for ( i = 0; i < 5; i++ )
buf[i] = x[i];

buf[5] = '\0';
printf( buf );
}

void print_first_5( char *x )
{
char tmp;

tmp = x[5];
x[5] = '\0';
printf( x );
x[5] = tmp;
}

As far as I can tell, the 2nd is both faster and takes less memory.
The two do the exact same thing, assuming that printf itself acts
nondestructively. If I used const to tell the compiler that
print_first_5 acts nondestructively on x in the 2nd version, the
compiler would think I was mistaken even though I'm correct. The point
is, the change can hardly be said to "change the very nature of this
function", and if this were deeply nested in a family of functions
using const arguments, a massive headache would arise.
Neither version is any damned good; no decent programmer
would write either one of them. A few flaws:

- Try the first version with the argument "X". What happens
when it tries to read elements [2] through [4] of this
two-element array?

- Try the second version with the argument "X". What happens
when it stores a zero in element [5] of this two-element
array? (Even if it doesn't segfault immediately, how sure
are you that whatever got clobbered isn't used by printf()?)

- Try either version with the argument "%solved". Somebody
doesn't know how to use printf() safely ...

- Try the second version with "Hello, world!" on an
implementation that puts string literals in read-only
memory. (Extra credit: defend your "I'm correct" claim.)

Arguments can be made for and against aspects of a programming
language, but arguments based on broken code carry little weight.

--
Eric Sosman
es*****@acm-dot-org.invalid
Jul 15 '06 #13
"Snis Pilbor" <sn********@yahoo.comwrote in message
>
Is const, in this context (ie passing const arguments to functions)....

1. A Java-like "babysitter" keyword based on the premise that all
programmers are idiots and must have their hands held at all times?
2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?
3. About as useful as a comment, with no other purpose but as a little
yellow sticky note saying "this function should act nondestructively on
this particular thing"?

I always assumed it was some combination of 1 and 3 and so I tend to
never, ever use the thing...
const is an addition to C.
It adds no functionality, and it doesn't really help the compiler to
optimise though someone might be able to come up with examples using pointer
aliasing or something similar.

It is a combination of 1 and 3. It is perfectly possible to write correct
code without const, unless you are an idiot programmer. So for idiot
programmers it might useful to be told that they are trying to write to a
const-qualified object.
Consider this function

void copy_string(char *str1, char *str2);

by looking at the prototype, you cannot tell which parameter is which.

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

tells you that the first parameter must be the source, so it is the other
way round to strcpy(). That's obviously handy.

The reason a lot of people don't like const is "const-poisoning". Once an
object is declared const, everything derived for it must be const, even it
is isn't really a constant.

The second problem is this

struct employee
{
char *name;
float salary;
};

void payroll(const employee *emp)
{

/* evil hacker */
strcpy(emp[0]->name, "Fred the Hacker");
pay(&emp[0]);
}
Jul 16 '06 #14
[The OP, writing about "const" qualifiers, asked whether const-qualified
arguments were...]
>>>2. Used to alert the compiler that some kind of extra optimization is
possible, which wouldn't be possible if the data in question were
manipulated? And if so, exactly what sort of optimization would this
be?
>Jack Klein posted:
>>The C standard does not define optimizations. There might well be
optimizations possible with data pointed to by a pointer to const, but
that is an implementation detail and off-topic here.
>Frederick Gotham wrote:
>Yes, that must be the exact reason why we have a "register" keyword.

I suppose "inline" has nothing to do with optimisation either.
In article <44***********************@news.xs4all.nl>
Skarmander <in*****@dontmailme.comwrote:
>Your sarcasm is misplaced; optimization is indeed not the primary intent of
"const". By that reasoning you might call static typing an optimization. It
may allow optimization, but that's not its primary benefit.
Indeed, it is quite a bit worse than this. C's "const" qualifiers
rarely allow any optimization at all!

Consider the following function:

int zog(const char *p) {
int result;

for (result = 0; *p; result++)
if (otherfunc())
break;
return result;
}

The loop inside this function repeatedly inspects *p. Well, we
claimed that *p was "const", so it will not change, right? Thus
the compiler can rewrite this as:

result = 0;
if (*p) {
while (otherfunc() == 0)
result++;
}
return result;

right?

Alas, wrong:

#include <stdio.h>

char buf[100];

int otherfunc(void) {
buf[42]--;
return 1;
}

int main(void) {
buf[42] = 12;

printf("%d\n", zog(&buf[42]));
return 0;
}

Each call to otherfunc() decrements buf[42], and *p inside zog is
just another name for buf[42]. The loop must in fact re-test *p
each time, and the code above must print 12.

In other words, even though zog() does not change *p, something
*else* might change it, despite the "const". Const does not mean
constant; it means "read-only". Read-only, but changing each time,
in this case.

In most (but not all) cases, "const" helps only when it is plainly
obvious that the variable has not changed, in which case, any decent
C compiler can substitute in the unchanged variable:

void zog2(void) {
const int i = 2;

while (i == 2)
other2();
}

Since nothing takes i's address here, it is impossible for i to
change. The const only helps make it clear that this is still
an infinite loop even if we pass &i to other2():

while (i == 2)
other2(&i);

Here, if i is *not* const, other2() can change it, but if i *is*
const, other2() cannot change it (without producing undefined
behavior, anyway).

The ugliest (in my opinion anyway) situation of all occurs when
C functions are forced to cast away "const"-ness from pointers in
their return values:

char *strchr(const char *s, int lookfor0) {
char lookfor = lookfor0;

for (; *s != c; s++)
if (*s == 0)
return NULL;
return (char *)s;
}

Fortunately, this mostly occurs in "legacy" routines like strchr(),
which the implementor (i.e., me :-) ) has to write for the user
(i.e., you) -- most programmers are not forced to do this.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.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.
Jul 16 '06 #15

Chris Torek wrote, in reference to const being used
to aid optimization:
C's "const" qualifiers
rarely allow any optimization at all!

Consider the following function:

int zog(const char *p) {
int result;

for (result = 0; *p; result++)
if (otherfunc())
break;
return result;
}
[Where otherfunc() manipulates a global that p
references.]

Isn't this the point of the restrict keyword? eg, your
function doesn't allow
int zog(const char *restrict p),
but if otherfunc didn't tweak *p, you could prototype
it that way and reap the benefits of the optimization.

Jul 16 '06 #16

Malcolm wrote:
The second problem is this

struct employee
{
char *name;
float salary;
};

void payroll(const employee *emp)
? void payroll(const employee **emp)
{

/* evil hacker */
strcpy(emp[0]->name, "Fred the Hacker");
? strcpy(emp->name, "Fred the Hacker");
pay(&emp[0]);
}
void payroll(const employee *emp);

In this case, the const keyword qualifies the object it points to as
constant. The object `name' is that one pointed by emp, so this is an
error:
/*(*emp).name = "C";*/

The object `*name' is pointed by name, not emp. That const does not
prevent following from being done:
*(*emp).name = 'c';

? void payroll(const employee **emp)

So does the const keyword applying to multiple-level pointer.
/*(**emp).name = "C";*/
*(**emp).name = 'c';

lovecreatesbeauty

Jul 16 '06 #17
>Chris Torek wrote, in reference to const being used
>to aid optimization:
>Consider the following function:

int zog(const char *p) {
int result;

for (result = 0; *p; result++)
if (otherfunc())
break;
return result;
}
In article <11**********************@75g2000cwc.googlegroups. com>,
Bill Pursell <bi**********@gmail.comwrote:
>[Where otherfunc() manipulates a global that p
references.]

Isn't this the point of the restrict keyword?
Yes. It turns out that "char *restrict p", or perhpas
"const char *restrict p", means what most people thought
"const char *p" was going to mean.
>eg, your function doesn't allow
int zog(const char *restrict p),
but if otherfunc didn't tweak *p, you could prototype
it that way and reap the benefits of the optimization.
Indeed. (By "prototype" I assume you mean "both declare and
define".) The "optimization" -- hoisting the *p test out of the
loop -- needs to takes place during compilation of the function
zog() itself, hence the the "restrict" has its main effect inside
the definition, rather than at some external prototype. Of course,
it is a good idea to make sure that every prototype declaration
for every function always matches the actual definition of the
function.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.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.
Jul 16 '06 #18
Chris Torek wrote:
Chris Torek wrote, in reference to const being used
to aid optimization:
Consider the following function:

int zog(const char *p) {
int result;

for (result = 0; *p; result++)
if (otherfunc())
break;
return result;
}

In article <11**********************@75g2000cwc.googlegroups. com>,
Bill Pursell <bi**********@gmail.comwrote:
[Where otherfunc() manipulates a global that p
references.]

Isn't this the point of the restrict keyword?

Yes. It turns out that "char *restrict p", or perhpas
"const char *restrict p", means what most people thought
"const char *p" was going to mean.
Although the below code is definitely poor style, is any rule actually
violated?

void f(const int *restrict p) {
*(int *) p = 0;
}
int main(void) {
int i = 1;
f(&i);
return i;
}

Jul 16 '06 #19

"lovecreatesbeauty" <lo***************@gmail.comwrote in message
>
Malcolm wrote:
>The second problem is this

struct employee
{
char *name;
float salary;
};

void payroll(const employee *emp)

? void payroll(const employee **emp)
>{

/* evil hacker */
strcpy(emp[0]->name, "Fred the Hacker");

? strcpy(emp->name, "Fred the Hacker");
Should be a dot.
Silly mistake, but easy to make. Or get rid of the [0].
The point is the hacker is allowed to insert his own name into the employee
list and, presumably, get the salary paid into his own account, despite the
fact that the distrustful high level programmer thinks the structure is
const.
>
> pay(&emp[0]);
}

void payroll(const employee *emp);

In this case, the const keyword qualifies the object it points to as
constant. The object `name' is that one pointed by emp, so this is an
error:
/*(*emp).name = "C";*/

The object `*name' is pointed by name, not emp. That const does not
prevent following from being done:
*(*emp).name = 'c';

? void payroll(const employee **emp)

So does the const keyword applying to multiple-level pointer.
/*(**emp).name = "C";*/
*(**emp).name = 'c';

lovecreatesbeauty
--
Buy my book 12 Common Atheist Arguments (refuted)
$1.25 download or $7.20 paper, available www.lulu.com/bgy1mm
Jul 16 '06 #20
(I was hoping someone else would answer this... no luck :-) )

In article <11**********************@35g2000cwc.googlegroups. com>,
Harald van Dijk <tr*****@gmail.comwrote:
>Although the below code is definitely poor style, is any rule actually
violated?

void f(const int *restrict p) {
*(int *) p = 0;
}
int main(void) {
int i = 1;
f(&i);
return i;
}
I think the answer to your question is "no", but I do not really
fully understand C99's "restrict".

Note that in this case, the compiler can "see" that *p is changed,
despite the "const". In my earlier example, the compiler cannot
(at least locally) see that *p is changed, even though p is declard
using "const char *p", so the compiler has to assume that the
"const" still means "changes after every subroutine call".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.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.
Jul 30 '06 #21

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: johny smith | last post by:
Well, I thought that I was creating a constant pointer, and would not be able to increment it without a compiler error. But this example compiles fine. The const is to the left of the * so...
4
by: Alfonzo Morra | last post by:
I've the ff code in cp assignmenent cstor: PB& PB::operator=( const PB& b) { if ( this != &b ) { PB *pb = new PB( b ) ; this = pb ; // <- Compiler barfs here } return *this ; }
5
by: kernel.lover | last post by:
hello, I want to know if a fuction say malloc is declared as void *malloc() then whats the significance of void here. Does void * is used when function has the flexibility to return any type of...
4
by: blah | last post by:
Hello everyone, Ive been trying to get my application to "click" on a button in another application using SendMessage, Ive gotten this far but Im not sure whats wrong with this code, here is the...
2
by: abubakarm | last post by:
Hi, There is a strang bug appearing not-so-often in my application. I'm pasting the stack calls window contents when my app crashes. Following it is: msvcr80d.dll!fastcopy_I(void *...
9
by: Bit Byte | last post by:
Can't seem to get my head around the point of a trait class - no matter how many times I read up on it - why not simply use functors or function pointers ? Anyone care to explain this in a...
26
by: =?gb2312?B?wNbA1rTzzOzKpg==?= | last post by:
i wrote: ----------------------------------------------------------------------- ---------------------------------------- unsigned char * p = reinterpret_cast<unsigned char *>("abcdg");...
10
by: joestevens232 | last post by:
Ok everything is good...I read in all my grades into each of the different arrays that they need to go in. Now Im trying to write a function that takes the grades and computes the average on a...
7
by: Adrian | last post by:
What is the best was to do this in c++. This is going to be used for unix util that should be able to have input piped to it or file name spec #include <stdio.h> int main(int argc, char...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.