0

So I have an array declared like this (it's not my code, and I will not modify it):

static const struct {
    int gsmesc;
    int latin1;
    int utf8_int;
    char *utf8;
    ...

} gsm_escapes[] = {
    {  10, 12 , 0x0C, "\x0C" },
    {  20, '^', 0x5E, "\x5E" }, 
    ...
};

Notice that the struct itself is untagged.

I want to iterate this array with a pointer (rather than an array subscript), and the best I could come up with is this, which compiles without any warnings:

typeof(*gsm_escapes) *esc;
...

esc = gsm_escapes;
while (esc++->gsmesc != -1) {

    esc = gsm_escapes;
    while (esc->gsmesc != -1) {

Is there a "proper" way to declare this pointer type since this approach seems uncharacteristically inelegant?

What is this type of data structure even called? I've been googling for a good while now and haven't come up with any primers that cover it.

robert
  • 4,612
  • 2
  • 29
  • 39
  • 1
    `typeof` seems perfectly legit. – Eugene Sh. Aug 24 '18 at 14:35
  • yeah but the bit about having to qualify the array with a `[0]` subscript to get the pointer is a bit *ewww* – robert Aug 24 '18 at 14:36
  • 1
    You can do `typeof(*gsm_escapes)` instead, I think... But why can't you iterate `gsm_escapes` directly? – Eugene Sh. Aug 24 '18 at 14:37
  • that did work, and it's a bit neater. If you don't mind I'm going to update my question to do that instead :) – robert Aug 24 '18 at 14:38
  • 2
    *I want to iterate this array with a pointer* **Why?** That's really just doing explicit pointer math that the compiler would happily do for you. – Caleb Aug 24 '18 at 14:40
  • 3
    I guess `typeof` is legit if and only if it does what the OP wants, @EugeneSh.. Since it's non-standard, that would depend on the implementation. – John Bollinger Aug 24 '18 at 14:40
  • @Caleb thanks for your insight but it doesn't really help steer me towards an answer ... – robert Aug 24 '18 at 14:41
  • Your answer to the question might steer our responses toward a better answer, though. That's why it's a comment -- I'm asking for clarification about what you're really trying to do. – Caleb Aug 24 '18 at 14:42
  • @JohnBollinger Right. But I am not aware of a portable solution (not workaround) to this. – Eugene Sh. Aug 24 '18 at 14:43
  • @Caleb Oh sorry, I thought it was clearly stated at the end? How to declare this pointer type and where this type of structure is documented. – robert Aug 24 '18 at 14:44
  • 1
    Bad code, file a bug report. – n. m. could be an AI Aug 24 '18 at 14:44
  • `typeof` is not in the C11 spec. See https://stackoverflow.com/q/12081502/2410359 – chux - Reinstate Monica Aug 24 '18 at 14:45
  • @chux I'm not a big fan of using *typeof* myself, but I guess the question is more related to the original array structure itself and the "proper" way to declare a pointer to it. – robert Aug 24 '18 at 14:46
  • 1
    That's the advice I have for you. If you don't like it, fine, go and find another. – n. m. could be an AI Aug 24 '18 at 14:48
  • The *proper* way to declare it is to give the structure a name, but you've already rejected the possibility of modifying the code. You could declare an identical structure in your own code with a name, but that's obviously problematic too. You could use the structure as is, and rely on the compiler to know what type is in the array, but you want to declare a pointer for some reason which you haven't shared. – Caleb Aug 24 '18 at 14:48
  • @n.m. except that in the question I specifically stated that wasn't an option. But thanks. – robert Aug 24 '18 at 14:49
  • 2
    I don't see where you have stated that. You have only stated *you* won't modify the code. I'm not proposing you do that. – n. m. could be an AI Aug 24 '18 at 14:52
  • Thank you @Caleb giving the structure a name does indeed seem to be "proper". With respect it's not the question I'm asking though. From my research the approach of declaring an identical struct is problematic since you can't be guaranteed that it will actually map to memory the same way. The reason for taking the pointer rather than (I presume you mean) array subscripting is "academic". – robert Aug 24 '18 at 14:53
  • 1
    In practice, @robert, it would be pretty surprising for two structs declared with identical form to have different layout, but two such declarations in the same translation unit (which then *must* be without tags) indeed do declare different types, and accessing an object of one of those types via an lvalue of the other type is indeed a violation of the strict aliasing rule, and therefore elicits undefined behavior. – John Bollinger Aug 24 '18 at 15:20
  • Also perhaps of concern is that the original struct was declared `static const` which might map to something different, to my own ad hoc struct declaration. Consts from what I understand often map to different memory regions and as such may have characteristics, alignment requirements, optimisations etc. – robert Aug 24 '18 at 15:25

1 Answers1

2

Using typeof is the only direct way to do this since the struct doesn't have a tag. It's also non-standard, so not all compilers may support it.

Your choices are:

  • Leave it as it is
  • Use array notation instead of pointer notation:

    int i=0;
    while (gsm_escapes[i++]->gsmesc != -1) {
    
        i=0;
        while (gsm_escapes[i]->gsmesc != -1) {
    
  • Create a typedef for the struct using typeof. That way the typeof expression only appears once:

    typedef typeof(*gsm_escapes) struct_gsm_escapes;
    ...
    struct_gsm_escapes *esc;
    
dbush
  • 205,898
  • 23
  • 218
  • 273
  • thank you - *"leave it as is"* is what I will be going with for now. As stated in the question your first and third suggestions are inadmissible. – robert Aug 24 '18 at 14:48
  • 1
    @robert I added another alternative using a `typedef` and removed the tagging option. Also, I can understand not wanting to change someone else's declaration, but why don't you want to use array syntax? – dbush Aug 24 '18 at 14:53
  • Not *everything* is possible despite some claims. – Eugene Sh. Aug 24 '18 at 14:55
  • Yeah but sometimes you just have to ask the experts to be sure. I think that the `typeof()` approach is probably the most appropriate. – robert Aug 24 '18 at 14:58