首先要明确名称(name)和实体(entity)的区别——一个数组名是一个名称(C里面就是指标识符(identifier)),不是实体(例如这个数组名表示的一个占据运行期内存空间的数组对象)。名称用来指称(denote)实体(ISO C中没有明确地定义这个概念,但是可以参照ISO C++的定义,把对象、函数等作为实体的外延,区别作为名称的标识符),是通过语言实现指称语义的重要成分,但不是语义的组成部分(C语言编译后的目标程序中可以不储存这些名称来实现操作语义,也体现了这点)。实体本身即是指称语义的一部分,最终通过目标程序的指令流实现的操作语义来体现。地址在这里是指亩模对象这一类实体的一种属性(attribute)。讨论名称的地址是没有意义的。(至于结构体名和地址有没有什么关系,具体后面再说。)数组名和地址看上去唯一有些关系信滑的情形(也是最流行的误解之一)是字面地作为一个表达式,在左值上下文(例如声明、作为&操作符或sizeof操作符的操作数)以外的场合下,数组名表示的数组可以隐式转换为指向这个数组的首个元素的指针。对于参数列表,数组的第一维长度可以忽略,也是因为这种隐式转换起作用的关系。像void fun(int a[]);和void fuint a[N]);(N是编译期确定的常数,例如#define N 3)还有void fun(int* a)都是等价的。但第一维以外就没办法忽略。具体的原因是,数组的类型由元素类型和长度决定,在转换成对应指针类型时长度被忽略,但元素类型不变。而所谓的多维数组实际上都只是静态的嵌套数组。举个例子,声明int array[3][10];后,array的类型是元素类型int[10](这本身又是一个数组类型)的数组,长度为3——3和10是编译期确定的常数。在函数参数列表书写接受array的参数类型时,3是可以省略的,就算把3替换成其它正整数也没问题;另一种等价的方式是使用数组对应的指针类型:int (*)[10](注意这个类型中的10是元素类型决定的,在转换为指针时不迅坦缓会丢失)。int**和int(*)[10]是不兼容的类型,无法隐式转换,因此参数列表中不能互相替换,LZ引用的那个回答明显是胡扯。不过倒也不是LS“二维数组显然无论如何也变不成指针数组”,要显式地转换,像(int**)array之类,也是可以的,但明显混淆了类型的语义,不建议这样做。如果非要实现二维动态数组,可以用结构体对象中储存指针和长度的方式,用malloc等动态分配空间进行实现,这里长度是运行期可变的。如果要作为函数的参数,可以传递结构体对象的指针。
和数组一样,结构体是一类类型的统称,尽管结构体的实例有时候也可以简称为结构体,但还是要注意区别以免混淆。结构体名是类型名,表示一个类型,在C这样的纯粹的静态类型语言中自然和地址没有半毛钱关系。结构体的实例(结构体对象)的名称表示一个对象,是一片具名的连续的内存空间,可以说它的第一个字节的地址是这个对象的地址(因为大小在编译期根据结构体的类型完全地确定且在运行期不变,所以通过地址可以无歧义地表示这个对象在运行期的存储方式)。
====
[原创回答团]
参数表里char a[][10]和char (*a)[10]是一码事。char **是二级指针,你得传指针数组或者指针的指针进去,二维数组显然无论如何也变不成指针数组。
结构体逻辑上的,没有实体也不会占用内存。结构体的意义在于程序认为一个数据属于某个结构体类型物旁的时候,就会根据结构体里规定的偏移位置获取数据历碰里的成员,而这些偏移位置是常数,没必要用内存去存。 (不过你说结构体指的结构体变量的话,变量名代表的就是结构肢蚂谈体数据的开始地址...姑且,这么说并不完全严谨。)
-----
那个答案里的类型都不匹配... 胡扯而已
多维数组作参数时,只有第一维长度岩耐可以省略,否则无法悔枣漏确定传入参数的碧烂类型。
具体理由可以参考这里:。
如果要使用“真正的”多维数组,需要自行定义动态数组结构体,
例如:
typedef struct vector_
{
int* ptr;
int length;
} vector;
typedef struct vector2_
{
vector* ptr;
int length;
} vector2;
使用前再分配空间和进行赋值,然后传递vector2类型的指针即可。
====
[原创回答团]
希望对你有帮助
不好意思 不知道。。。