C中数组的const和typedef

C中数组的const和typedef,c,arrays,constants,typedef,C,Arrays,Constants,Typedef,在C语言中,可以使用以下结构typedef数组: typedef int table_t[N]; 这里,表t现在定义为Nint的数组。声明的任何变量,如表\t现在将作为int的普通数组 这种构造的要点是用作函数中的参数类型,例如: int剂量测定法(表t); 相对等效的功能原型可能是: int剂量测量(int*t); 第一个构造的优点是它强制执行N作为表的大小。在许多情况下,强制执行此属性比依赖程序员正确地找出此条件更安全 现在一切都好了,只是为了保证表的内容不会被修改,有必要使用cons

在C语言中,可以使用以下结构
typedef
数组:

typedef int table_t[N];

这里,
表t
现在定义为N
int
的数组。声明的任何变量,如
表\t
现在将作为
int
的普通数组

这种构造的要点是用作函数中的参数类型,例如:

int剂量测定法(表t);

相对等效的功能原型可能是:

int剂量测量(int*t);

第一个构造的优点是它强制执行
N
作为表的大小。在许多情况下,强制执行此属性比依赖程序员正确地找出此条件更安全

现在一切都好了,只是为了保证表的内容不会被修改,有必要使用
const
限定符

以下陈述相对容易理解:

int剂量测量(常数int*t);

现在,
doSomething
保证它不会修改作为指针传递的表的内容。 那么,这个几乎相等的结构呢

int剂量测量(常数表);

这里的
const
是什么?表的内容,还是指向表的指针? 如果指针是常量,是否有另一种方法(C90兼容)来保留定义表的大小并告诉其内容是常量的能力

请注意,有时还需要修改表的内容,因此不能将
const
属性嵌入到typedef定义中

[编辑]感谢迄今为止收到的优秀答案。 总结如下:

  • 最初假设的大小为N是完全错误的。它的行为基本上与普通指针相同
  • const
    属性的行为也将与指针相同(与指针类型的typedef形成鲜明对比,如下@random所示)
  • 要强制实施尺寸(这不是最初的问题,但现在非常重要…),请参阅

表格内容将保持不变。很容易用这个代码检查

#include<stdio.h>

typedef int table_t[3];
void doSomething(const table_t t)
{
    t++;    //No error, it's a non-const pointer.
    t[1]=3; //Error, it's a pointer to const.

}

int main()
{
    table_t t={1,2,3};
    printf("%d %d %d %ld",t[0],t[1],t[2],sizeof(t));
    t[1]=5;
    doSomething(t);
    return 0;
}
#包括
typedef int table_t[3];
无效剂量测定(常数表)
{
t++;//没有错误,它是一个非常量指针。
t[1]=3;//错误,它是指向常量的指针。
}
int main()
{
表t={1,2,3};
printf(“%d%d%d%ld”,t[0],t[1],t[2],sizeof(t));
t[1]=5;
剂量测定法(t);
返回0;
}

首先,您弄错了,函数原型

int doSomething(table_t t);
int doSomething(int* t);
它们完全相等。对于函数参数,第一个数组维度始终重写为指针。因此,无法保证接收到的阵列的大小

const
-对数组的限定始终应用于数组的基类型,因此这两个声明

const table_t a;
int const a[N];
是等价的,对于函数参数

int doSomething(const table_t t);
int doSomething(int const* t);

标准6.7.6.3规定:

作为“类型数组”的参数声明应调整为“类型的限定指针”

这意味着当您将函数参数声明为
const int
数组类型时,它将衰减为指向
const int
(数组中的第一个元素)的指针。在这种情况下相当于
const int*

还请注意,由于上述规则,指定的数组大小不会增加额外的类型安全性!这是C语言的一大缺陷,但事实就是如此

尽管如此,最好像以前一样使用固定宽度声明数组,因为静态分析器或智能编译器可能会生成关于不同类型的诊断

第一个构造的优点是它将N强制为表的大小

我不知道你在这里是什么意思。在什么情况下它会“强制”它?如果将函数声明为

int doSomething(table_t t);
将不强制执行数组大小。我想强制执行尺寸,你得走另一条路

int doSomething(table_t *t); // equivalent to 'int (*t)[N]'
这里的常数是什么

至于
常数
。。。当
const
应用于数组类型时,它会一直“下拉”到数组元素。这意味着
const table\u t
是常量
int
s的数组,即它相当于
const int[N]
类型。这样做的最终结果是数组变得不可修改。在函数参数声明上下文中,
const table\u t
将转换为
const int*

但是,请注意一个在本例中并不明显的特殊细节:数组类型本身保持非常量限定。是单个元素变成了
const
。事实上,在C中不可能对数组类型本身进行常量限定。任何这样做的尝试都会使常量限定“筛选”到单个元素

这种特性导致了数组常量正确性方面相当令人不快的结果。例如,此代码不会在C中编译

table_t t;
const table_t *pt = &t;

尽管从const正确性的角度来看它看起来很天真,并且将针对任何非数组对象类型进行编译。C++语言更新了它的正确性规则来解决这个问题,而C继续坚持它的旧方法。

数组类型和指针类型不是100%等价的,即使在这样的上下文中,你最终得到函数函数的指针类型。您的错误在于假设

const
如果是指针类型,其行为方式也会相同

要扩展ARBY的示例,请执行以下操作:

typedef int table_t[3];
typedef int *pointer_t;

void doSomething(const table_t t)
{
    t++;    //No error, it's a non-const pointer.
    t[1]=3; //Error, it's a pointer to const.
}

void doSomethingElse(const pointer_t t)
{
    t++;    //Error, it's a const pointer.
    t[1]=3; //No error, it's pointer to plain int
}
它的作用类似于
int*const
,但
const pointer\u t
却相当于
int*const

(另外,免责声明,POSIX不允许使用以_t结尾的用户定义名称,它们是为将来的扩展保留的。)