Const correctness for array pointers?

后端 未结 3 1419
北恋
北恋 2020-11-30 09:59

Someone made an argument saying that in modern C, we should always pass arrays to functions through an array pointer, since array pointers have strong typing. Example:

3条回答
  •  庸人自扰
    2020-11-30 10:53

    OP describes a function func() that has the following signature.

    void func(size_t n, const int (*arr)[n])
    

    OP wants to call it passing various arrays

    #define SZ(a) (sizeof(a)/sizeof(a[0]))
    
    int array1[3];
    func(SZ(array1), &array1);  // problem
    
    const int array2[3] = {1, 2, 3};
    func(SZ(array2), &array2);
    

    How do I apply const correctness to array pointers passed as parameters?

    With C11, use _Generic to do the casting as needed. The cast only occurs when the input is of the acceptable non-const type, thus maintaining type safety. This is "how" to do it. OP may consider it "bloated" as it is akin to this. This approach simplifies the macro/function call to only 1 parameter.

    void func(size_t n, const int (*arr)[n]) {
      printf("sz:%zu (*arr)[0]:%d\n", n, (*arr)[0]);
    }
    
    #define funcCC(x) func(sizeof(*x)/sizeof((*x)[0]), \
      _Generic(x, \
      const int(*)[sizeof(*x)/sizeof((*x)[0])] : x, \
            int(*)[sizeof(*x)/sizeof((*x)[0])] : (const int(*)[sizeof(*x)/sizeof((*x)[0])])x \
      ))
    
    int main(void) {
      #define SZ(a) (sizeof(a)/sizeof(a[0]))
    
      int array1[3];
      array1[0] = 42;
      // func(SZ(array1), &array1);
    
      const int array2[4] = {1, 2, 3, 4};
      func(SZ(array2), &array2);
    
      // Notice only 1 parameter to the macro/function call
      funcCC(&array1);  
      funcCC(&array2);
    
      return 0;
    }
    

    Output

    sz:4 (*arr)[0]:1
    sz:3 (*arr)[0]:42
    sz:4 (*arr)[0]:1
    

    Alternatively code could use

    #define funcCC2(x) func(sizeof(x)/sizeof((x)[0]), \
        _Generic(&x, \
        const int(*)[sizeof(x)/sizeof((x)[0])] : &x, \
              int(*)[sizeof(x)/sizeof((x)[0])] : (const int(*)[sizeof(x)/sizeof((x)[0])])&x \
        ))
    
    funcCC2(array1);
    funcCC2(array2);
    

提交回复
热议问题