5

In the document of iconv, the function synopsis is this:

#include <iconv.h>

size_t iconv (iconv_t cd, const char* * inbuf, 
      size_t * inbytesleft, 
      char* * outbuf, 
      size_t * outbytesleft);

But, when I check the iconv.h in my system, the function synopsis is this:

extern size_t iconv (iconv_t __cd, char **__restirct __inbuf,
      size_t *__restrict __inbytesleft,
      char **__restirct __outbuf,
      size_t *__restrict __outbytesleft);

In these two function synopses, one is const char **, but the other one is only char **.

Why is the function synopsis in the document different from the one in my system? And why does the iconv function need a non-const inbuffer?

The version of my g++ is 6.3.0.

akshayk07
  • 2,092
  • 1
  • 20
  • 32
LeLe570929726
  • 87
  • 1
  • 7

2 Answers2

5

The problem with iconv() is that it's not part of the C standard, but it's specified in two different standards. One of them is POSIX-1.2008:

#include <iconv.h>

size_t iconv(iconv_t cd, char **restrict inbuf,
       size_t *restrict inbytesleft, char **restrict outbuf,
       size_t *restrict outbytesleft);

The other one is SUSv2:

#include <iconv.h>

size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
    char **outbuf, size_t *outbytesleft);

They differ in constness of **inbuf, so if you want to stay portable between both standards, you'll have to pass a non-const **inbuf, unfortunately.

Edit: As this is a double pointer, the problem is even worse, see my answer here. In a nutshell, these specifications aren't compatible in either direction...


What you linked as "document of iconv" is the documentation of GNU libiconv, which is intended to be used on platforms that don't natively provide iconv() -- this one obviously follows the SUSv2 specification.

The header file you find on your system belongs to glibc, your platform's C library, and this implementation follows the POSIX-1.2008 specification.

  • POSIX 2008 is same as SUSv4. They have long ceased to exist separately. So SUSv2 and SUSv4 are not compatible? ;-) – P.P Aug 29 '17 at 13:14
  • I'd say that Posix 1.2008 is an update to SUSv2; to just say that they are "different standards" (while technically correct) is somewhat misleading. In any case, SUSv2 lists two different prototypes for `iconv`, one of which is in the interface specification whicg you reference (with `const`) and the other of which (without `const`) is in the header specification at http://pubs.opengroup.org/onlinepubs/7908799/xsh/iconv.h.html. The discrepancy was fixed in Issue 6, but that leaves open the question of which of the two prototypes apply for SUSv2... – rici Aug 29 '17 at 19:19
  • ... here, the only real guide is the statement in http://pubs.opengroup.org/onlinepubs/7908799/xsh/interfaces.html: "Implementations of XSI-conformant systems will make all necessary symbols visible **as described in the Headers section** of this specification." (emphasis added) That seems to imply that the `iconv.h` specification is the one to be used, and thus the `const` in the glibc prototype is incorrect. (That would also be consistent with the later change.) – rici Aug 29 '17 at 19:21
  • @felix: Ok, the Gnu libiconv, if you prefer. Regardless of where that iconv.h comes from, it seems to me to be wrong. :) – rici Aug 30 '17 at 08:01
  • I think you'll find that Gnu libiconv no longer has `const` either. (Changelog indicates it was essentially removed in 2007 or so.) – rici Aug 30 '17 at 08:07
  • None of POSIX 2008, Glibc and GNU libiconv have `const` now. Besides, `const` not what's asked in the question. But the "incompatibility" is a big claim not supported by facts considering POSIX 2008 is a successor standard to SUS2. Unless you have evidence to support that `libiconv` still follows SUS2 (that'd be a surprise considering they've changed the interface to be compatible with a later POSIX standard), this answer is misleading in many ways. – P.P Aug 30 '17 at 08:24
  • @P.P. `const` **is** what this question is about and do you have any reference that glibc declares `inbuf` as `const`? See the documents I linked, are they wrong? If yes, please provide sources. –  Aug 30 '17 at 08:31
  • Ok, I misread. I didn't claim Glibc uses `const` - I said **none** of them have const. Except the incorrect claim about the question ("Besides, const not what's asked in the question.") in my previous comment, everything still stands. – P.P Aug 30 '17 at 08:47
  • @P.P. see here the [latest libiconv documentation](https://www.gnu.org/savannah-checkouts/gnu/libiconv/documentation/libiconv-1.7/iconv.3.html) ... –  Aug 30 '17 at 09:17
  • @felix: that documentation is from version 1.7 whereas the latest version of libiconv is 1.15. Having said that, it appears that the documentation for version 1.15 does not conform to the prototypes in the headers provided with that version, so there is a documentation error. – rici Aug 30 '17 at 16:32
  • Also, glibc did include the `const` prior to version 2.2. See `ChangeLog.11` in the glibc source. – rici Aug 30 '17 at 16:45
0

const char* * inbuf, vs. char **__restirct __inbuf,, I guess. – Sourav Ghosh

indeed - the restrict informs the compiler that the pointer object will not change. This declaration was actually done this way to allow better optimisation of the generated code.

Using restrict may actually on the higher optimisation level lead to the worst code.

https://godbolt.org/g/uhfVCe

0___________
  • 60,014
  • 4
  • 34
  • 74
  • 3
    "*You cant use `const` and `restrict`*" <- reference? I can combine both very well (with `const` applied to the data and `restrict` to the pointer) and it makes sense, semantically. –  Aug 29 '17 at 13:02
  • I was imprecise indeed - will remove – 0___________ Aug 29 '17 at 13:06