指针和数组与sizeof运算符(嵌入式笔试必考题)

来源:互联网 发布:综漫 收集数据做主神 编辑:程序博客网 时间:2024/06/03 19:40

指针和数组与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。

 




原创粉丝点击