c和指针

c与指针

函数的参数

c语言中所有的参数都是以“传值调用”方式进行传递,这意味着函数将获得参数值的一份拷贝。这样,函数可以放心修改这个拷贝值,而不必担心会修改调用程序实际传递给它的参数。这个行为与modula和pascal中的值参数相同。
c的规则很简单:所有参数都是传值调用。但是,如果被参数传递的参数是一个数组名并且在函数中引用了函数内的元素,那么在程序中对数组元素进行修改实际上修改的是调用程序中的数组元素。数组将访问调用程序的数组元素,数组并不会被复制。这个行为称被为“传址调用”,也就是许多其他语言所实现的var参数。
请记住的两个规则:
1.传递给函数的标量参数是传值调用。
2.传递给函数数组参数在行为上就像它们通过传址调用。

//对值进行偶校验
int even_parity(int value,int n_bits)
{
	int parity = 0;
	/*计算值中值为1的位的个数*/
	while(n_bits > 0)
	{
		parity += value &1;
		value >>= 1;
		n_bits -=1;
	}
	/*如果计算器的最低位是0,则返回TURE 表示1的位数是偶数个*/
	return (parity % 2) ==0; 
}

程序中说明了 标量函数参数的传值行为。函数检查第一个参数是否满足偶校验,也就是它的二进制位模式中1的个数是否为偶数。函数的第二个参数指定第一个参数中有效位的数目。函数一次一位地对第一个参数值进行移位,所以每个位迟早都会出现在最右边的那个位置。所有的位逐个加在一起,所以在循环结束后,我们得到第一个参数值的位模式中1的个数。最后,对这个数进行测试,看看它的最低有效位是不是1,如果不是,那么说明1的个数就是偶数个。
这个函数的有趣特性是在它的执行过程中,它会破坏这两个参数的值。但这并无妨,因为参数是通过传值调用的,函数所使用的值是实际参数的一份拷贝。破环这份拷贝并不会影响原先的值。

//交换调用程序中的两个整数(没有效果)
void swap(int x,int y)
{
	int temp;
	temp =x;
	x= y;
	y= temp;
}

这个程序与第一个程序不同:它希望修改调用程序传递的参数。这个函数的目的是交换调用程序所传递的这两个参数的值。但这个程序是无效的,因为它实际交换的是参数的拷贝,原先的参数值并未进行交换。

//交换调用程序中的两个整数
void swap(int *x ,int *y)
{
	int temp;
	temp = *x;
	*x = *y;
	*y = temp;
}

这个程序的函数期望接受的参数是指针,所以我们应该按照下面的方式调用它:
swap(&a,&b);

//把一个数组的所有元素都设置为零
void clear_array(int array[],int n_elements)
{
	//从数组最后一个元素开始,逐个清除数组中的元素,注意前缀自增避免了越出数组边界的可能性
	while(n_elements > 0)
	array[--n_elements] = 0;
}

这个程序是把一个数组的所有元素都设置为0.n_elements是一个标量参数,所以它是传值调用的。在函数中修改它的值并不会影响调用程序中的对应参数。另一方面,函数确实把调用程序的数组的所有元素设置为0.数组参数的值是一个指针,下标引用实际上是对这个指针执行间接访问操作。
这个例子可以解释在声明数组参数时为什么不指定它的长度是合法的,因为函数并不为数组元素分配内存。间接访问操作将访问调用程序中的数组元素。这样,一个单独的函数可以访问任意长度的数组。对于pascal程序员而言,这是个福音。但是,函数并没有办法判读数组参数的长度,所以函数如果需要这个值,它必须作为一个参数显式地传递给函数。

猜你喜欢

转载自blog.csdn.net/qq_37272520/article/details/82826013
今日推荐