C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > 数组名不等于指针 sizeof()函数求数组大小错误

数组名不等于指针 sizeof()函数求数组大小错误问题及解决

作者:Z小旋

这篇文章主要介绍了数组名不等于指针 sizeof()函数求数组大小错误问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

前言 

今天在项目中需要求采样点的数量并且遍历,采样点用数组存储,自定义了一个函数想要用sizeof求其长度,然后遍历,结果失败了,查阅之后发现以下问题:

在main函数中,sizeof是可以正常工作的

#include <stdio.h>

int Number[10];   

int main()
{
	int size = sizeof(Number);
	printf("数组大小为:%d\n",size);
	int len = sizeof(Number)/sizeof(int);
	printf("数组共有%d个数据\n",len);

	return 0;
}

输出:

但是在自定义函数中就不可以了,如下:

#include <stdio.h>

int Number[10]; 

void print_1(int n[])
{
	int size = sizeof(n);
	printf("数组大小为:%d\n",size);
	int len = sizeof(n)/sizeof(int);
	printf("数组共有%d个数据\n",len);
}
  

int main()
{
	
	print_1(Number); 
	
	return 0;
}

那么我们首先要知道sizeof函数的功能:

sizeof是获取数据在内存中所占用的存储空间,以字节为单位来计数。

那么这个时候有的同学就会有问题了,两次传入的都是数组的首地址,为什么主函数中就可以,自定义函数中就不行呢?

得益于谭老爷子的C语言书籍普及量和销量,很多人认为数组名就是指向数组首地址的一个指针,但其实这个说法是错误的!

我们用一个最简单的例子,假设数组名是一个指针,那么:

#include <stdio.h>

int Number[10]; 

int *Number2;
  
int main()
{  
	int a=sizeof(Number);
	int b=sizeof(Number2);
	
	printf("a的大小为:%d \n b的大小为 %d\n",a,b); 
	
	return 0;
}

首先我们要知道,单纯的数组名,不是指针

数组名是一个标识符,它标识出我们之前申请的一连串内存空间,而且这个空间内的元素类型是相同的——即数组名代表的是一个内存块及这个内存块中的元素类型 。

只是在大多数情况下数组名会“退化”(C标准使用的decay和converted这两个词)为指向第一个元素的指针。

而指针不是一种聚合类的数据结构,它保存着某一种类型的对象的地址(void*除外),也说它指向这个对象。

我们可以通过这个地址访问这个对象。用一个图来解释,其中a代表了整个我们声明的内存块,p仅仅指向了一个char类型的对象

char a[] = {'h' 'e' 'l' 'l' 'o'};
char b[] = {'w' 'o' 'r' 'l' 'd'};

char *p=b;

这是怎么一回事呢?

我们看一下C99标准:

C99 6.3.2.1 Lvalues, arrays, and function designators 中第三段是这样说的:

Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue. If the array object has register storage class, the
behavior is undefined.

这段话的意思是: 数组名只有在

这三种情况下不会发生退化(array decay)

其余情况下调用数组名,都会退化成指向数组首地址的指针

再深入的话,就是要了解指针的sizeof

结论

也就是说在c语言中,数组名在函数的调用中退化成了一个指针,对函数的参数使用Sizeof,sizeof获取的结果就是指针的大小,而不是数组本身的大小

再了解一下Sizeof的处理时间

sizeof是C语言的一种单目操作符(但有人也不这么以为,认为它是一种特殊的宏),如C语言的其他操作符++、–等一样。它并不是函数

sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定,简单的说其作用就是返回一个对象或者类型所占的内存字节数。

也就是说,Sizeof是一个C语言的操作符,那么他的处理阶段在编译阶段,也就是说你程序没有运行前,sizeof(arr)就被替换成了一个固定的常量,那么对于动态生成的数组大小是不能用sizeof来算出来的。

解决方法

在函数中多加一个参数,表示数组的长度

#include <stdio.h>

int Number[10]; 

void print_1(int n[], int len)
{

	printf("数组大小为:%d\n",len);
	
	printf("数组共有%d个数据\n",len/sizeof(int));

}
  
int main()
{
	
	print_1(Number,sizeof(Number)); 
	
	return 0;
}

以上就是问题的总结。仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文