int a[10];
int b[10];
a = b; // illegal
typedef struct {
int real;
int imag;
} complex;
complex c,d;
c = d; //legal
[我意识到在第一种情况下a和b是地址,而在第二种情况下是符号]
关于历史信息,这可能会有趣:http://cm.bell-labs.com/who/dmr/chist.html
B语言中,声明数组将为数组分配内存,就像C语言一样,但变量的名称用于定义指向该数组的指针。Ritchie在C语言中对此进行了更改,因此名称“is”数组,但在使用时可以衰减为指针:
今天的C保留了规则,即数组类型的值在表达式中出现时将转换为指向组成数组的第一个对象的指针。
这个发明使得大多数现有的B代码能够继续工作,尽管语言语义发生了基本变化。那些为了调整其起始位置而给数组名称赋新值的少数程序——这在B和BCPL中是可能的,在C中毫无意义——很容易修复。
如果在那个非常早期的阶段,Ritchie定义a = b
来复制数组,那么他试图从B到C移植的代码将不会那么容易修复。由他定义的那个代码将会出错,然后他可以修复它。如果他让C复制数组,那么他将默默地改变代码复制数组的含义,而不是重新设置用于访问数组的名称。
仍然有一个问题,“为什么这个特性在40年后没有被添加”,但我认为这就是为什么一开始没有它。实现它需要付出努力,而这种努力实际上会使早期版本的C更糟,因为将B和BCPL代码移植到C略微困难。所以Ritchie当然没有这样做。
a = b;
等值语境时,数组名 a 和 b 都表示 &a[0]
和 &b[0]
的地址。这通常被称作数组“衰退”为指针。int
组成的数组和由20个int
组成的数组是不同的且不兼容的类型。如果你有一个固定大小的数组,就像你问题中的代码一样,只有部分元素当前是相关的;你可能有一个10个元素的数组,但你只当前使用了前5个元素。逐个处理此类数组元素使得更容易只处理当前处于活动状态的元素(这是你自己要跟踪的)。&
(地址)运算符的操作数时;sizeof
的操作数时;以及int func(char s[]);
被调整为指针参数:int func(char *s);
。int a[10];
int b[10];
/* ... */
a = b; /* Why not? */.
数组名是一个常量指针,因此您无法更改它所指向的内容。
假设您在最后一行的意思是 c = d 是合法的,那么这只是将一个非常量变量复制到另一个非常量变量,这是完全合法的。
a 实际上是数组的第一个元素的“指针”,它是一个常量“指针”,因此您正在尝试分配一个 l-“指针”。
您可以通过以下方式实现您想要做的事情:
struct arraystruct
{
int t[10];
};
struct arraystruct a,b;
a=b;
编辑:我忘了提到有一些例外情况,其中数组不应被视为指针:
- 您可以使用sizeof(array),但不能使用sizeof(pointer)
- 字面字符串的数组
- a和&a是相同的
a
会衰变为struct arraystruct* const
,因为a
被用于表达式中。因此答案并不是真正的错误,只是简化了。 - Lundin这是因为你使用的数组类型是所谓的静态数组,即其内存位于堆栈上。如果你使用动态数组(带指针)则你的赋值将是合法的(但可能会出现内存泄漏)。这将是一次浅拷贝。
另请参见C++中的静态数组与动态数组。
int (*array)[10] = malloc(10*sizeof(int));
,那么我肯定会认为它是语言中的数组。此外,这些评论并没有帮助到OP。 - Lundinarray
仍然是一个指向数组的指针,而不是数组本身。sizeof(array)
将给出指针的大小,而不是10 * sizeof(int)
的大小。 - Blagovest Buyuklievint (*array)[10] = malloc(10*sizeof(int));
是否少了一个*?我的理解是,这段代码创建了一个包含10个指向int值的静态指针数组,并且应该为int (*array)[10] = malloc(10*sizeof(int*));
。 - fredo
int foo[10]; &foo;
@cnicutar - Keith Thompson