四.函数,数组和指针
假定要编写一个对数组进行操作的函数,目的是要此函数返回数组内所有元素的
和,调用函数如下:
total=sum(marbles);
那么函数原型应该为:
int sum(int *ar,int n)
{
int i;
int total=0;
for(i=0;i<n;i++)
total+=ar[i];
return total;
}
#include <stdio.h>
#define SIZE 10
int sum(int ar[], int n);
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sum(marbles, SIZE);
printf("The total number of marbles is %ld.\n", answer);
printf("The size of marbles is %zd bytes.\n",
sizeof marbles);
return 0;
}
int sum(int ar[], int n)
{
int i;
int total = 0;
for( i = 0; i < n; i++)
total += ar[i];
printf("The size of ar is %zd bytes.\n", sizeof ar);
return total;
}
以上程序是一个使用函数sum()的程序。注意marbles的大小为40字节,因为数组
有10个元素,每个元素占用4个字节,总计40个字节。而ar是指向数组首地址的指
针,指针的大小为4字节。
1.使用指针参数
使用数组的函数需要知道何时开始和结束数组。函数sum()使用一个指针参量来
确定数组的开始点,使用一个整形参量来指明数组元素个数。另外一种方法是使
用两个指针,第一个指针指明数组的起始位置,第二个指针指明数组的结束地址
。
#include <stdio.h>
#define SIZE 10
int sump(int * start, int * end);
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sump(marbles, marbles + SIZE);
printf("The total number of marbles is %ld.\n", answer);
return 0;
}
int sump(int * start, int * end)
{
int total = 0;
while (start < end)
{
total += *start;
start++;
}
return total;
}
函数sump()使用第二个指针来控制循环次数:
while(start<end)
因为这是一个对于不相等关系的判断,所以处理的最后一个元素将是end所指向的
位置之前的元素。这意味着end实际上指向的位置是在数组最后一个元素之后。这
种越界是合法的。
#include <stdio.h>
int data[2] = {100, 200};
int moredata[2] = {300, 400};
int main(void)
{
int * p1, * p2, * p3;
p1 = p2 = data;
p3 = moredata;
printf(" *p1 = %d, *p2 = %d, *p3 = %d\n",
*p1 , *p2 , *p3);
printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",
*p1++ , *++p2 , (*p3)++);
printf(" *p1 = %d, *p2 = %d, *p3 = %d\n",
*p1 , *p2 , *p3);
return 0;
}
这个程序体现了指针的优先级。
五.指针操作
c提供了6种基本的指针操作,下面的程序将具体演示这些操作。
#include <stdio.h>
int main(void)
{
int urn[5] = {100,200,300,400,500};
int * ptr1, * ptr2, *ptr3;
ptr1 = urn;
ptr2 = &urn[2];
printf("pointer value, dereferenced pointer, pointer address:\n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n",
ptr1, *ptr1, &ptr1);
ptr3 = ptr1 + 4;
printf("\nadding an int to a pointer:\n");
printf("ptr1 + 4 = %p, *(ptr4 + 3) = %d\n",
ptr1 + 4, *(ptr1 + 3));
ptr1++;
printf("\nvalues after ptr1++:\n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n",
ptr1, *ptr1, &ptr1);
ptr2--;
printf("\nvalues after --ptr2:\n");
printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %p\n",
ptr2, *ptr2, &ptr2);
--ptr1;
++ptr2;
printf("\nPointers reset to original values:\n");
printf("ptr1 = %p, ptr2 = %p\n", ptr1, ptr2);
printf("\nsubtracting one pointer from another:\n");
printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %d\n",
ptr2, ptr1, ptr2 - ptr1);
printf("\nsubtracting an int from a pointer:\n");
printf("ptr3 = %p, ptr3 - 2 = %p\n",
ptr3, ptr3 - 2);
return 0;
}
可以对指针变量执行的操作有:赋值,求值或者取值,取指针地址,将一个整数
加给指针,增加指针的值,从指针中减去一个整数,减小指针的值,求差值,比
较。
六.保护数组内容
指针是直接传递地址的,所以增加了程序的效率,但是这也有缺点,它无法保证
原始数据的完整性。对于一个数组我们可能在多个函数中运用到它,但是在一些
函数中如果使用了指针就改变了数组的值,无法再其他函数中运用。所以,我们
必须要保证原始数据的完整性。
我们对形式参量使用const来保证完整性。例如:
int sum(const int ar[],int n);//原型
int sum(const int ar[],int n);//定义
{
int i;
int total=0;
for(i=0;i<n;i++)
total+=ar[i];
return total;
}
这样使用const并不是要求原始数组是固定不变的,这只是说明函数在处理数组时
,应把数组当作是固定不变的。
#include <stdio.h>
#define SIZE 5
void show_array(const double ar[], int n);
void mult_array(double ar[], int n, double mult);
int main(void)
{
double dip[SIZE] = {20.0, 17.66, 8.2, 15.3, 22.22};
printf("The original dip array:\n");
show_array(dip, SIZE);
mult_array(dip, SIZE, 2.5);
printf("The dip array after calling mult_array():\n");
show_array(dip, SIZE);
return 0;
}
void show_array(const double ar[], int n)
{
int i;
for (i = 0; i < n; i++)
printf("%8.3f ", ar[i]);
putchar('\n');
}
void mult_array(double ar[], int n, double mult)
{
int i;
for (i = 0; i < n; i++)
ar[i] *= mult;
}
上面程序中第一个函数不需要修改数组,所以使用const,而第二个函数需要修改
数组,所以不使用const。
假定要编写一个对数组进行操作的函数,目的是要此函数返回数组内所有元素的
和,调用函数如下:
total=sum(marbles);
那么函数原型应该为:
int sum(int *ar,int n)
{
int i;
int total=0;
for(i=0;i<n;i++)
total+=ar[i];
return total;
}
#include <stdio.h>
#define SIZE 10
int sum(int ar[], int n);
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sum(marbles, SIZE);
printf("The total number of marbles is %ld.\n", answer);
printf("The size of marbles is %zd bytes.\n",
sizeof marbles);
return 0;
}
int sum(int ar[], int n)
{
int i;
int total = 0;
for( i = 0; i < n; i++)
total += ar[i];
printf("The size of ar is %zd bytes.\n", sizeof ar);
return total;
}
以上程序是一个使用函数sum()的程序。注意marbles的大小为40字节,因为数组
有10个元素,每个元素占用4个字节,总计40个字节。而ar是指向数组首地址的指
针,指针的大小为4字节。
1.使用指针参数
使用数组的函数需要知道何时开始和结束数组。函数sum()使用一个指针参量来
确定数组的开始点,使用一个整形参量来指明数组元素个数。另外一种方法是使
用两个指针,第一个指针指明数组的起始位置,第二个指针指明数组的结束地址
。
#include <stdio.h>
#define SIZE 10
int sump(int * start, int * end);
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sump(marbles, marbles + SIZE);
printf("The total number of marbles is %ld.\n", answer);
return 0;
}
int sump(int * start, int * end)
{
int total = 0;
while (start < end)
{
total += *start;
start++;
}
return total;
}
函数sump()使用第二个指针来控制循环次数:
while(start<end)
因为这是一个对于不相等关系的判断,所以处理的最后一个元素将是end所指向的
位置之前的元素。这意味着end实际上指向的位置是在数组最后一个元素之后。这
种越界是合法的。
#include <stdio.h>
int data[2] = {100, 200};
int moredata[2] = {300, 400};
int main(void)
{
int * p1, * p2, * p3;
p1 = p2 = data;
p3 = moredata;
printf(" *p1 = %d, *p2 = %d, *p3 = %d\n",
*p1 , *p2 , *p3);
printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",
*p1++ , *++p2 , (*p3)++);
printf(" *p1 = %d, *p2 = %d, *p3 = %d\n",
*p1 , *p2 , *p3);
return 0;
}
这个程序体现了指针的优先级。
五.指针操作
c提供了6种基本的指针操作,下面的程序将具体演示这些操作。
#include <stdio.h>
int main(void)
{
int urn[5] = {100,200,300,400,500};
int * ptr1, * ptr2, *ptr3;
ptr1 = urn;
ptr2 = &urn[2];
printf("pointer value, dereferenced pointer, pointer address:\n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n",
ptr1, *ptr1, &ptr1);
ptr3 = ptr1 + 4;
printf("\nadding an int to a pointer:\n");
printf("ptr1 + 4 = %p, *(ptr4 + 3) = %d\n",
ptr1 + 4, *(ptr1 + 3));
ptr1++;
printf("\nvalues after ptr1++:\n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n",
ptr1, *ptr1, &ptr1);
ptr2--;
printf("\nvalues after --ptr2:\n");
printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %p\n",
ptr2, *ptr2, &ptr2);
--ptr1;
++ptr2;
printf("\nPointers reset to original values:\n");
printf("ptr1 = %p, ptr2 = %p\n", ptr1, ptr2);
printf("\nsubtracting one pointer from another:\n");
printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %d\n",
ptr2, ptr1, ptr2 - ptr1);
printf("\nsubtracting an int from a pointer:\n");
printf("ptr3 = %p, ptr3 - 2 = %p\n",
ptr3, ptr3 - 2);
return 0;
}
可以对指针变量执行的操作有:赋值,求值或者取值,取指针地址,将一个整数
加给指针,增加指针的值,从指针中减去一个整数,减小指针的值,求差值,比
较。
六.保护数组内容
指针是直接传递地址的,所以增加了程序的效率,但是这也有缺点,它无法保证
原始数据的完整性。对于一个数组我们可能在多个函数中运用到它,但是在一些
函数中如果使用了指针就改变了数组的值,无法再其他函数中运用。所以,我们
必须要保证原始数据的完整性。
我们对形式参量使用const来保证完整性。例如:
int sum(const int ar[],int n);//原型
int sum(const int ar[],int n);//定义
{
int i;
int total=0;
for(i=0;i<n;i++)
total+=ar[i];
return total;
}
这样使用const并不是要求原始数组是固定不变的,这只是说明函数在处理数组时
,应把数组当作是固定不变的。
#include <stdio.h>
#define SIZE 5
void show_array(const double ar[], int n);
void mult_array(double ar[], int n, double mult);
int main(void)
{
double dip[SIZE] = {20.0, 17.66, 8.2, 15.3, 22.22};
printf("The original dip array:\n");
show_array(dip, SIZE);
mult_array(dip, SIZE, 2.5);
printf("The dip array after calling mult_array():\n");
show_array(dip, SIZE);
return 0;
}
void show_array(const double ar[], int n)
{
int i;
for (i = 0; i < n; i++)
printf("%8.3f ", ar[i]);
putchar('\n');
}
void mult_array(double ar[], int n, double mult)
{
int i;
for (i = 0; i < n; i++)
ar[i] *= mult;
}
上面程序中第一个函数不需要修改数组,所以使用const,而第二个函数需要修改
数组,所以不使用const。