Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

c - pointer to array not compatible to a pointer to 'const' array?

In a C module (aka, compilation unit), I want to have some private data, but expose it read-only to the outside world. I achieve that by having a field in a struct declared in my .c file and a function declared in my .h file that returns a pointer to const to that field. For example, this could look like the following for a string:

// header:

typdef struct foo foo;

const char *foostr(const foo *f);

// implementation:

struct foo
{
    char *str;
};

const char *foostr(const foo *f)
{
    return foo->str;
}

Now my problem is, I have an array of objects that are themselves arrays. So in my struct, I have a pointer to an array, and from my function, I try to return a pointer to the corresponding const array. Consider the following example code:

#include <stdlib.h>
#include <stdint.h>

typedef uint8_t shape[64];

typedef struct foo
{
    shape *shapes;
} foo;


foo *createfoo(void)
{
    foo *f = malloc(sizeof *f);
    if (!f) return 0;

    // 10 empty shapes:
    f->shapes = calloc(10, sizeof *(f->shapes));

    if (!f->shapes)
    {
        free(f);
        return 0;
    }

    return f;
}

const shape *fooshapes(const foo *f)
{
    return f->shapes;
}

Compiling this with gcc -c -std=c11 -Wall -Wextra -pedantic, I get the following warning:

constarr.c: In function ‘fooshapes’:
constarr.c:31:13: warning: pointers to arrays with different qualifiers are incompatible in ISO C [-Wpedantic]
     return f->shapes;
            ~^~~~~~~~

I understand a double pointer isn't compatible to a double pointer to const, and also the reason for it, but I don't think this is related, or is it? So, why isn't it allowed to implicitly convert a pointer to an array to a pointer to a const array? And any ideas what I should do instead?

What I did now is adding an explicit cast like this:

const shape *fooshapes(const foo *f)
{
    return (const shape *) f->shapes;
}

This of course silences the compiler and I am almost sure it will always work correctly in practice. The "const hole" can't exist in this case, as with an array, there is no non-const inner pointer. But it still leaves me with two further questions:

  • Is my assumption correct that this doesn't lead to a hole in const correctness?
  • Does the explicit cast violate the standard here?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is indeed the same double pointer issue you refer to in the question.

You can convert pointer-to-T to pointer-to-const-T. But const applied to an array qualifies the element type, not the array type (C11 6.7.3.9), so that's not what you're trying to do here. You're not trying to convert pointer-to-array-of-T to pointer-to-const-array-of T, but rather trying to convert to pointer-to-array-of-const-T, and those two types are not compatible in C.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...