-2

I came across this question while doing the exercises in Advanced Programming in the Unix Environment by Stevens:

  • The argument to perror is defined with the ISO C attribute const, whereas the integer argument to strerror isn't defined with this attribute. Why?

Is the perror function defined with the const attribute because we usually pass a literal string to it?

void perror(const char *s);

char *strerror(int errnum);
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
narendraj9
  • 131
  • 2
  • 7
  • The question also makes no sense, since top-level CV qualifiers on function arguments don't affect the declaration. – Kerrek SB May 17 '14 at 15:49
  • Why has the question been asked in the book if it makes no sense? – narendraj9 May 17 '14 at 16:06
  • 1
    Not all books are great. In fact, many books are awful. Your biggest enemy as a programmer are other, poor programmers. They write code, comments, wikis, and also books. You're generally outnumbered. – Kerrek SB May 17 '14 at 16:13
  • 1
    You need to understand the difference between `T const *` and `T * const` (and `T const * const`). Then the question evaporates. – Kerrek SB May 17 '14 at 16:16
  • @KerrekSB You mean this book-- http://www.apuebook.com/ ? – narendraj9 May 17 '14 at 16:19
  • @KerrekSB I don't think the question is even remotely related to the difference between a pointer to const data and const pointer to mutable data. – narendraj9 May 17 '14 at 16:22
  • @narendra: the issue _is_ to do with why `const` is applied to pointer arguments and not to non-pointer arguments, and does depend in part on the differences between (1) non-const pointer to non-const data, (2) non-const pointer to const data, (3) const pointer to non-const data, (4) const pointer to const data. Certainly, the reason `perror()` takes a non-const pointer to const data is to permit the passing of string literals which formally have the type const array of char, which becomes a pointer to const data when passed to a function. – Jonathan Leffler May 17 '14 at 16:26
  • There are probably questions that this is a duplicate of. – Jonathan Leffler May 17 '14 at 16:28
  • APUE is one of the better books on the Unix API. However, it is not a tutorial on C. This question is about C, and only coincidentally about the Unix API (the two examples are standard C functions, and therefore also part of the Unix API, but the question could be asked in a book about standard C). It is important to understand the answer to the question. – Jonathan Leffler May 17 '14 at 16:31

3 Answers3

5

When an argument to a function is declared const, it means the function won't modify the argument passed.

Usually, an argument is declared const, when the modification affects the value outside of the function, e.g. when passing a pointer to something.

  • strerror(int errnum) even if the function modifies the passed integer, it won't modify the value outside of the function, because it is passed by value. Therefore, you don't need strerror(const int errnum).
  • perror(const char *s)

    • if perror modifies s, it doesn't modify the pointer outside of the function. Therefore, you don't need perror(char *const s) (a constant pointer)

    • if perror would modify *s, it would modify the contents of the string, s points to. Therefore, you need perror(const char *s) (a pointer to constant value) to make sure that your string isn't modified by perror

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
  • At the danger of repetition, I think it's worth stressing that `sterror(int errnum)` and `strerror(const int errnum)` are *the same declaration*. [Live demo](https://ideone.com/MS7opV). – Kerrek SB May 18 '14 at 11:34
2

The perror() function takes a pointer to constant data so that you can pass a string literal to it and be assured that the function won't modify the string it is passed.

  • A called function taking an integer argument can modify its integer argument without affecting anything in the calling function.

  • A called function with an argument that is a pointer to non-const data can modify the data in the calling function via that argument.

  • A called function with an argument that is a pointer to const data cannot modify the data in the calling function without abusing the type system (using a cast).

Of course, a function with a pointer argument can change its copy of the pointer (for example, by incrementing it), but since the pointer value is local to the called function, that doesn't affect anything in the calling function either.

So, there's no need for const on non-pointer arguments to functions because the value of the argument is a local variable.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Hm, this is all a bit muddled. But you can't really rescue the original, wrong question (neither function argument is `const`, which as I said isn't part of the function type anyway). – Kerrek SB May 17 '14 at 16:15
-1

The former passes a pointer to a const char (by value), the string should be treated as const in the called function as well. The latter passes an int (again, by value). So yes.

tommyo
  • 531
  • 4
  • 10