2011-05-09 64 views
8

我正在研究C中的最后一个明天,并且对于运算符sizeof有个问题。sizeof数组澄清

比方说,int的大小是32位,指针是64位。

如果有一个功能:

int 
foo (int zap[]) 
{ 
    int a = sizeof(zap); 
    return a; 
} 

因为zap是一个指针,foo将返回8,因为这是多少个字节如何需要存储这个特殊的指针。然而,用下面的代码:

int zip[] = { 0, 1, 2, 3, 4, 5 }; 
int i = sizeof(zip); 

i6 * sizeof(int) = 6 * 4 = 24

为什么是它的每个元素的元素的sizeof(zip)返回数倍大小,而sizeof(zap)返回a的大小指针?是不是zap的大小不明确,zip不是?编译器知道zip6元素,但不知道可能有多大。

回答

8

这是C语法中的一种不对称。在C中,不可能将一个数组传递给一个函数,所以当你在一个函数声明中使用数组语句时,编译器会将其作为指针读取。

在C中当您使用的阵列中的表达的阵列被隐式转换为指针到它的第一元件和例如为当调用一个函数正是发生大多数情况下。在下面的代码:

int bar[] = {1,2,3,4}; 
foo(bar); 

阵列被转换为指针的第一个元素,并且是函数接收什么。

内隐转换的这条规则并不总是能够适用。当你发现例如sizeof操作符阵列上,甚至&运营商(-的地址)的作品原来的阵列(即sizeof(*&bar) == 4*sizeof(int))上。

在C A功能不能recevive数组作为参数,它只能接收一个指针的第一个元素,或一个指针数组...或中,必须用一个结构阵列。

即使你把函数声明括号之间的数...

void foo(int x[4]) 
{ 
    ... 
} 

这个数字完全是由编译器忽略...那声明编译器是完全等同于

void foo(int *x) 
{ 
    ... 
} 

和例如甚至调用它传递一个数组具有不同的尺寸将不会触发任何错误...

int tooshort[] = {1,2,3}; 
foo(tooshort); /* Legal, even if probably wrong */ 

(实际上是一个编译器可能给予警告,但代码是完全合法的C和必须的,如果编译器遵循标准被接受)

如果你认为有关数组这个规则时,函数参数是奇怪那么我同意,但这是如何定义C语言的。

+0

数量并不被编译器忽略,INT X [4]作为函数参数意味着你必须通过的_exactly_ 4个元素的数组的指针。这与在代码中其他地方写入'int(* x)[4]'是一样的。除此之外,这个答案指出了这个问题:参数的数组语法与程序中其他地方声明的数组具有不同的含义。它是C语言的“特征”之一。为避免混淆,请始终使用“int * x”表示法来表示参数。 – Lundin 2011-05-09 06:56:59

+0

您可以指出它在标准中写入括号内的数字必须等于传递数组的大小吗?提示:考虑到你根本不能传递一个数组并且该函数实际上只接收一个指针,这将是一个奇怪的要求。当调用用'FOO的函数(巴)'其中'bar'是一个数组,数组已被转换为指针**即使对于编译器**被认为是函数调用之前。对转换中已经放弃的尺寸信息施加限制是没有意义的。 – 6502 2011-05-09 07:06:29

+0

@Lundin,对于数组参数的第一维,no基本上被忽略。此外,C99还有关键字'static'的可能性,以指定该函数对于项目至少*。但参数的类型仍然是'int *'。 – 2011-05-09 07:51:45

2

因为zip是数组并且编译器知道它的大小,所以编译时的编译时间为。它只是使用两个不同的东西,一些相同的符号在C.很平常的情况下

int 
foo (int zap[]) 

完全等同于

int 
foo (int *zap) 

编译器不会有任何想法大ZAP怎么可能是(所以它留给找到程序员的任务)。

+1

这个C常见问题是**无价**:http://c-faq.com/aryptr/index.html – cnicutar 2011-05-09 06:30:00

+0

即使您在括号内放置一个数字,但它仍然只是一个指针,而数字本身完全被编译器忽略。所以它不是一个关于编译器不知道大小的问题......它的C语言对函数参数列表中的数组有特殊的奇怪规则。 – 6502 2011-05-09 06:58:12

+0

@ 6502你是对的,很好的电话。在括号内加上一个数字会产生同样的效果,这就是为什么它被强烈劝阻的原因。 – cnicutar 2011-05-09 07:00:44

-1

因为它已经静态初始化6个元素。

+0

有人想澄清downvote?我的回答和其他2人一样,只是更简洁一点而已? – 2011-05-09 06:28:16

+0

我没有做downvote,但是如果“zip”被初始化或者没有,那真的没关系。这个问题全是关于C的奇怪的函数参数语法。 – Lundin 2011-05-09 07:02:07

0

zip的大小在编译时已知,zap的大小不是。这就是为什么你得到sizeof(zap)上的指针大小和sizeof(zip)上的数组大小。

2

zip6 * sizeof(int)的内存块,因此它的大小为24(在您的体系结构上)。 zap(在函数声明中它也可以写为int *zap),但是可以指向任何内存地址,编译器无法知道从这个地址(甚至包含这个地址)开始分配了多少空间。

0

在某些情况下,指针会衰减。函数调用就是其中之一。