指针和数组与sizeof运算符(嵌入式笔试必考题)
参考朱有鹏的C语言高级专题
1、sizeof不是一个函数,是一个关键字。
这个关键字是用来返回()里面的变量或者数据类型占用的内存字节数
sizeof存在的价值:
在不同的平台下面,各种数据类型所占用的字节数是不一定相同的
int 在32位系统中为4字节,在16位系统中为2字节。
所以程序需要使用sizeof判断当前变量、数据类型在当前环境占用几个字节。
2、
char str[] = "hello";
2.2 sizeof(str) = 6;
2.3 sizeof(str[0]) = 1;
2.4 strlen(str) = 5;
解析:2.2、为什么是为6,因为sizeof关键字是判断()里面东西,实际的大小,而不管里面到底有没有放东西。
2.3、str[0]是代表这个字符串数组的第一个元素的大小,那么当然就是当前的数据类型的大小1个字节
2.4、strlen(str)=5,就是指字符串的长度,那么字符串的长度就肯定不能包括最后的'\0'
3、
Char str[] = “hello”;
Char *p = str;
这里我么需要的是指针变量本身还是指针变量所指向的那个变量。
strlen这个函数是有要求的,用来返回一个字符串的长度。
注意字符串的长度是不计算字符串末尾的’\0’
一定要注意strlen接收的参数必须是一个字符串
Sizeof(p) = 4
sizeof(*p) = 1 这里相当于sizeof(char)
strlen(p) = 5 相当于字符串的长度strlen(str)
3、int n = 10;
Sizeof(n) = 4
Int b[100];
Sizeof(b) = 400;
sizeof测试一个变量本身,和sizeof测试这个变量的类型,
结果是一样的。
要么一直传递变量,要么一直传递类型。
Sizeof(数组名)的时候,数组名不做左值也不做右值,
纯粹就是数组名的含义,那么sizeof(数组名)实际上返回的是
整个数组所占用的内存空间。(是以字节为单位的整个数组所占用的内存空间)
Void fun (int b[100])
{
Sizeof(b); //这里传参的值是4
}
如果是函数传递数组元素的话,那么就是数组的指针。
函数传参形参是可以传递数组的,
实际传递的不是整个数组而是
数组的首元素和首地址,实际相当于传递了一个指针。
指针指向数组的首元素首地址。
因为a在函数func内部就是指针,而不是数组。
这里面你用数组和指针来做形参是没有任何的区别的。
在子函数内,a是我们传进来的数组的指针(或者说是它的首地址)
这个是很重要的C语言的基础。就是我们在一个函数如果需要操作数组的话,
那么我们需要两个参数:一个数组的首地址,一个是数组的长度
最后我再来讲一个东西,
我有一个数组
Int a[100];
Int b = sizeof(a)/sizeof(a[0]);
Printf(“b = %d.\n”,b);
得到的是数组的元素的个数。
这样的写法,虽然看起来很长,这样写,程序具有自动化。
这样写的话,程序改动的地方比较少。
Sizeof是用来测试结构体的大小。
4、指针和函数之间传参
4.1、普通变量作为函数形参
函数传参的时候,普通变量作为函数的时候:
形参和实参打印出来的地址是不一样的,从而来判断:
两个变量是两个不同的变量。
4.2、&a和&b不同,说明a和b不是同一个变量
(在内存中a和b是独立的2个内存空间)
说明a和b是两个变量。
但是他们之间是有关联的,实际上b是a赋值得到的。
(2)当我们用实参来赋值,形参的值等于实参
原因是函数调用时把实参的值赋值给了形参。
这就是很多书上写的“传值调用”相当于实参做右值,形参做左值。
4.3、数组作为函数形参
数组也是可以做函数的形参。
函数名作为形参传参的时候,实际传递的不是整个数组,而是数组
首元素的首地址,所以这两个是没有区别的。
所以在我们子函数内部,传进来的数组名就等于是一个指向数组首元素的首地址的指针。
Void func2(int a[])
{
}
跟子函数内传参得到的首元素首地址得到的值是
一样的。和外面得到的数组首元素首地址的值是相同的。
很多人把这种特性叫做传址调用。
所谓的传址调用,就是我们调用子函数时传了地址(也就是指针)
此时可以通过传进去的地址,访问实参。
数组作为函数形参的话,因为数组名做形参的传递实际只是一个指针
所以可以不给数组的大小。
4.4、指针作为函数形参
和数组作为函数形参是一模一样的,也就是func2是一样的。
这就好像是指针方式来访问数组,和数组方式来访问数组是一样的
4、6结构体变量作为函数形参
Struct结构体,使用这个结构体作为传参。
结构体传进去的值也是传值传递的,跟普通变量传递的时候也是这样的。
实际上和我们普通变量(类似于int之类)传参时表现是一模一样的。
因为结构体一般都很大,所以如果直接用结构体变量进行传参,那么
函数调用的效率就会很低
因为在函数传参的时候需要将实参赋值给形参。
所以当传参的变量越大,效率就会越低。
那么就是不要传变量,改传变量的指针。
指针的大小永远是4字节
Struct a =
{
.a = 1,
.b = 8,
}
Void func5(struct A *a1)
{
Printf(“sizeof(a1) = %d.\n”,sizeof(a1));
Printf(“sizeof(*a1) = %d.\n”,sizeof(*a1));
Printf(“a1 = %p.\n”,a1);
Printf(“a1->b = %d.\n”,a1->b);
}
这个是结构体变量的对齐的方式而已。所以大小是8。