Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you implement strtol under const-correctness?

Tags:

c

According to http://www.cplusplus.com/reference/cstdlib/strtol/ this function has a signature of long int strtol (const char* str, char** endptr, int base).

I wonder, though: If it gets passed a const char * to the beginning of the string, how does it manage to turn that into a non-const pointer to the first unprocessed character without cheating? What would an implementation of strtol look like that doesn't perform a const_cast?

like image 851
Enno Avatar asked Jan 13 '16 12:01

Enno


People also ask

How does strtol work in C?

In the C Programming Language, the strtol function converts a string to a long integer. The strtol function skips all white-space characters at the beginning of the string, converts the subsequent characters as part of the number, and then stops when it encounters the first character that isn't a number.

What library is strtol in C?

C Programming/stdlib. h/strtol strtol is a function in the C programming language that converts a string into a long integer. strtol stands for string to long. It is included in the C standard library header file stdlib.

What does strtol return if fails?

The strtol() function returns the result of the conversion, unless the value would underflow or overflow. If an underflow occurs, strtol() returns LONG_MIN. If an overflow occurs, strtol() returns LONG_MAX. In both cases, errno is set to ERANGE.

What is Endptr in C?

endptr − This is the reference to an object of type char*, whose value is set by the function to the next character in str after the numerical value. base − This is the base, which must be between 2 and 36 inclusive, or be the special value 0.


2 Answers

How do you implement strtol under const-correctness?

You don't, because strtol's definition is inherently not const-correct.

This is a flaw in the C standard library.

There are several standard functions that take a const char* argument (expected to point the beginning of a character array) and give back a non-const char* pointer that can be used to modify that array.

strchr is one example:

char *strchr(const char *s, int c);

For example:

#include <string.h>
int main(void) {
    const char *s = "hello";
    char *ptr = strchr(s, 'h');
    *ptr = 'H';
}

This program has undefined behavior. On my system, it dies with a segmentation fault.

The problem doesn't occur in strchr itself. It promises not to modify the string you pass to it, and it doesn't. But it returns a pointer that the caller can then use to modify it.

The ANSI C committee, back in the late 1980s, could have split each such function into two versions, one that acts on const character arrays and another for non-const arrays:

char *strchr(char *s, int c);
const char *strcchr(const char *s, int c);

But that would have broken existing pre-ANSI code, written before const existed. This is the same reason C has not made string literals const.

C++, which inherits most of C's standard library, deals with this by providing overloaded versions of some functions.

The bottom line is that you, as a C programmer, are responsible for not modifying objects you've defined as const. In most cases, the language helps you enforce this, but not always.

As for how these functions manage to return a non-const pointer to const data, they probably just use a cast internally (not a const_cast, which exists only in C++). That's assuming they're implemented in C, which is likely but not required.

like image 100
Keith Thompson Avatar answered Sep 17 '22 09:09

Keith Thompson


Most likely it just uses casting.

There are numerious functions that have this same property in standard library. Sacrifiying type safety over simplicity is likely reason, since you cannot overload functions as in C++.

They expect that programmer takes responsibility, and doesn't edit endptr if str is, for example, a string literal.

With it's limited type system, C is practical language for practical people.

like image 31
user694733 Avatar answered Sep 18 '22 09:09

user694733