本篇博客将讲解的知识:
(1)指针的使用和传址调用
(2)数组名的理解
1、指针的使用和传址调用
(1)strlen 的模拟实现
库函数strlen的功能是求字符串的长度,统计的是字符串中'\0'之前的字符的个数。
strlen函数的原型:
size_t strlen (const char *str);
注意:size_t是无符号整型,strlen是求字符串的长度的,长度不可能为负数。
代码实现:
注意:size_t类型的数据用%zd打印。
(2)传值调用和传址调用
学习指针的目的是使用指针解决问题。
例如:写一个函数,交换两个整型变量的值。
传值调用:
结论:实参传递给形参的时候,形参会单独创建一份临时空间来接收实参,对形参的修改不会影响实参。
传值调用:传的是变量中的内容
传址调用:
传址调用:传的是变量的地址
总结:
传址调用,可以让被调函数和主调函数之间建立真正的联系,在被调函数内部可以修改主调函数中的变量;所以,未来函数中只是需要主调函数中的变量值来实现计算,就可以采用传值调用。如果函数内部要修改主调函数中的变量的值,就需要传址调用。
被调函数:在main函数外定义的函数。
主调函数:在main函数中调用函数。
2、数组名的理解
x86(32位环境)下执行下列代码:
从这个代码中我们发现:数组名和数组首元素的地址是一样的。
数组名就是数组首元素的地址
如果数组是int类型的数组,则该数组首元素的地址是4个字节中地址最小的那个地址。(int类型的数据占4个字节)
如果数组是首元素的地址,那么输出的应该是4(32位平台下)/8(64位平台下)。
其实数组名就是数组首元素的地址,但是有两个例外。
(1)sizeof(数组名),sizeof中单独放数组名表示整个数组,计算的是数组的大小,单位是字节。
(2)&数组名,这里的数组名是表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的。比如:&数组名+1!=数组名+1,但是,在一维数组中,&数组名==数组首元素的地址,但是含义是不同的)。
除了这两个例外之外,任何地方使用数组名,数组名都表示首元素的地址。
上面代码中,&arr[0]和&arr[0]+1相差4个字节,arr和arr+1也相差4个字节,这是因为arr和&arr[0]都是数组首元素的地址,+1就是跳过一个元素。
但是&arr和&arr+1相差40个字节(001BF75C-001BF734==00000028),16进制的28转换为十进制为40(2*16的一次方+8*16的零次方==40),这是因为&arr是整个数组的地址,+1就是跳过整个数组。