C数组声明和赋值?
Posted
技术标签:
【中文标题】C数组声明和赋值?【英文标题】:C array declaration and assignment? 【发布时间】:2010-10-19 04:12:21 【问题描述】:我在结构here 上提出了类似的问题,但我试图弄清楚 C 如何处理诸如分配变量之类的事情,以及如果它们在功能上相同,为什么不允许将它们分配给彼此。
假设我有两个数组:
int x[10];
int y[10];
为什么 x = y 不能编译?如果它们都是像那样的相同“签名”,那么您不应该来回分配它们吗?
我可以以允许我在 C 中执行此操作的方式声明这些吗?对我来说,你能够做到这一点是有道理的,但也许有办法做到这一点?结构的 typedef 似乎是解决方案,数组声明和赋值是否相同?
感谢你们的帮助,我是 *** 的新手,但到目前为止它对我来说是一个非常好的资源!
【问题讨论】:
【参考方案1】:简单地说,数组是不可赋值的。它们是“不可修改的左值”。这当然引出了一个问题:为什么?请参阅此问题以获取更多信息:
Why does C++ support memberwise assignment of arrays within structs, but not generally?
数组不是指针。 x
这里确实指的是一个数组,尽管在许多情况下这个“衰减”(隐式转换)为指向它的指针第一个元素。同样,y
也是数组的名称,而不是指针。
您可以在结构中进行数组赋值:
struct data
int arr[10];
;
struct data x = /* blah */;
struct data y;
y = x;
但是你不能直接用数组来做。使用memcpy
。
【讨论】:
该代码仍然没有完成他想要它做的事情,不是吗?也许我错了,但我的印象是他希望将 y 数组的内容复制到 x 中。 是的。幸运的是,许多其他回复表明 memcpy() 是正确的选择。我会添加它... “数组的名称实际上是该数组的第一个元素的地址。\您在此处提供的示例代码试图分配给不是左值的东西。”:对于为了子孙后代,我想我会注意到投票率最高的答案中的这两个句子都是错误的。首先,数组的名称绝对不是指针(例如想想 sizeof()),它在许多情况下只是简单地衰减为指针。其次,数组名是一个左值,只是不是一个可修改的左值。 我在劫持这个答案。它获得最高票数并被接受,但包含不正确的信息,并且用户早已不复存在。希望这可以解决问题。【参考方案2】:int x [sz];
int *y = x;
这样编译,y
将与x
相同。
【讨论】:
y
将是一个等同于 &x[0]
的指针,由于数组到指针的转换,但它不会“相同”,因为 x
是一个数组,而不是一个指针。【参考方案3】:
这里的一些消息说数组的名称会产生其第一个元素的地址。并非总是如此:
#include <stdio.h>
int
main(void)
int array[10];
/*
* Print the size of the whole array then the size of a pointer to the
* first element.
*/
printf("%u %u\n", (unsigned int)sizeof array, (unsigned int)sizeof &array[0]);
/*
* You can take the address of array, which gives you a pointer to the whole
* array. The difference between ``pointer to array'' and ``pointer to the
* first element of the array'' matters when you're doing pointer arithmetic.
*/
printf("%p %p\n", (void*)(&array + 1), (void*)(array + 1));
return 0;
输出:
40 4
0xbfbf2ca4 0xbfbf2c80
【讨论】:
【参考方案4】:为了分配数组,您必须在数组中分配值。
即。 x=y 等价于
for(int i = 0; i < 10 < ++i)
x[i] = y[i];
【讨论】:
这就是为什么我要提供等价物! 它给人的印象是 x=y 是一个有效的陈述 实际上在 OP 中已经提到 x=y 无法编译。 x=y 对数组来说不可能是这个问题的全部内容,Naveen。【参考方案5】:为了补充 Blank 的回答,我设计了以下程序:
localhost:~ david$ cat test.c
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char * argv [])
struct data
int c [2];
x, y;
x.c[0] = x.c[1] = 0;
y.c[0] = y.c[1] = 1;
printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]);
printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]);
x = y;
printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]);
printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]);
return 0;
执行时,输出如下:
x.c 0x7fff5fbff870 0 0
y.c 0x7fff5fbff860 1 1
x.c 0x7fff5fbff870 1 1
y.c 0x7fff5fbff860 1 1
重点是说明结构值的复制是如何发生的。
【讨论】:
【参考方案6】:当说“int x[10]”时,是在说“为 10 个整数保留一些空间并传递给我一个指向该位置的指针”。因此,要使副本有意义,您需要对所指向的内存进行操作,而不是“内存位置的名称”。
因此,要在此处复制,您将使用 for 循环或 memcpy()。
【讨论】:
【参考方案7】:我使用了 C 编译器,它可以编译得很好......并且在运行时代码会使 x 指向 y 的数组。
你看,在 C 中,数组的名称是一个指向数组开头的指针。事实上,数组和指针本质上是可以互换的。您可以使用 any 指针并像数组一样对其进行索引。
在 70 年代初开发 C 时,它适用于在抽象上略高于汇编语言的相对较小的程序。在那种环境下,能够轻松地在数组索引和指针数学之间来回切换非常方便。另一方面,复制整个数据数组是一件非常昂贵的事情,而且几乎没有什么值得鼓励或从用户那里抽象出来的事情。
是的,在当今时代,将数组的名称简写为“整个数组”而不是“指向数组前面的指针”会更有意义。然而,C 并不是在现代设计的。如果您想要一种语言,请尝试 Ada。 x := y 完全符合您的期望;它将一个数组的内容复制到另一个。
【讨论】:
友好的随机 ping。 :) 毫无疑问,您(现在)知道,数组的名称不是指针。以上是关于C数组声明和赋值?的主要内容,如果未能解决你的问题,请参考以下文章
C#/.NET6期01C#基础_10_11_12数组声明引用类型如果没有赋值的话则默认值为null
C#/.NET6期01C#基础_10_11_12数组声明引用类型如果没有赋值的话则默认值为null