首页>Program>source

有人争论说,在现代C语言中,由于数组指针具有强类型,因此我们应始终通过数组指针将数组传递给函数.示例:

void func (size_t n, int (*arr)[n]);
...
int array [3];
func(3, &array);

听起来这可能是防止所有类型相关的错误和数组越界错误的好主意.但是后来发生在我身上,我不知道该如何应用const正确性。

如果我做 void func (size_t n, const int (*arr)[n]) 那么它是正确的.但是由于指针类型不兼容,我无法再传递数组. int (*)[3]const int (*)[3] .限定符属于所指向的数据,而不属于指针本身。

在调用方中进行显式强制转换会破坏提高类型安全性的整个想法。

如何将const正确性应用于作为参数传递的数组指针? 有可能吗?


编辑

就像信息一样,有人说像这样通过指针传递数组的想法可能起源于MISRA C ++:2008 5-2-12.参见例如PRQA的高完整性C ++标准.

最新回答
  • 7天前
    1 #

    除了强制转换外,没有其他方法可以做到.这是以这种方式传递数组的想法的重大缺陷.

    这是将C规则与C ++规则进行比较的类似线程.从比较中我们可以得出结论,因为您的用例是有效的,但是C不允许隐式转换,因此C规则的设计不是很好.另一个这样的例子是 T **的转换 到 T const * const * ; 这是安全的,但C不允许。

    请注意,自 n 不是一个常数表达式,那么 int n, int (*arr)[n]int n, int *arr相比,没有任何附加的类型安全性 .您仍然知道长度(n),并且超出范围仍然是沉默的未定义行为,而传递实际上不是长度的数组则是沉默的未定义行为 n .

    在传递非VLA数组的情况下,如果编译器必须报告是否传递了指向错误长度数组的指针,则此技术具有更大的value。

  • 7天前
    2 #

    C标准指出( :§6.7.3/ 9):

    If the specification of an array type includes any type qualifiers, the element type is so- qualified, not the array type .[...]

    因此,如果是 const int (*arr)[n]const 应用于数组的元素而不是数组 arr 本身. arr 当您将类型为pointer的参数传递给int的array [n]时,类型为指向const int的array [n]的指针.两种类型都不兼容.

    How do I apply const correctness to array pointers passed as parameters? Is it at all possible?

    不可能.不使用显式强制转换就无法在标准C中执行此操作.

    但是,GCC允许将此作为​​扩展名:

    In GNU C, pointers to arrays with qualifiers work similar to pointers to other qualified types. For example, a value of type int (*)[5] 可用于初始化 const int (*)[5]类型的变量 . These types are incompatible in ISO C because the const qualifier is formally attached to the element type of the array and not the array itself

    extern void
     transpose (int N, int M, double out[M][N], const double in[N][M]);
     double x[3][2];
     double y[2][3];
     ...
     transpose(3, 2, y, x);
    

    进一步阅读:用C和C ++中的const限定符指向数组的指针

  • 7天前
    3 #

    OP描述了 func()函数 具有以下签名.

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

    OP希望通过各种数组来调用它

    #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?

    对于C11,请使用 _Generic 根据需要进行铸造.当输入是可接受的非 const时,仅强制转换 类型,从而保持类型安全.这是"方法". OP可能会认为它"膨胀",因为与此类似.这种方法将宏/函数调用简化为仅1个参数。

    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;
    }
    

    输出

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

    或者代码可以使用

    #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);
    

  • android:为什么使用Xamarin Forms的iOS应用程序无法显示"真棒字体"?
  • java:将参数传递给JDBC PreparedStatement