由若干基类型相同的指针所构成的数组,称为 指针数组 (Pointer Array )。指针数组的每个元素都是一个指针,且这些指针指向相同数据类型的变量。
此时指针代表行
/*a是一个二维数组
p=a; 把p初始化为a*/
p 第0行
p+i 第i行
*(p+i) 第i行第0列
*(p+i)+j 第i行第j列
*(*(p+i)+j) 取出第i行第j列的内容
指针代表列
/*区分指针数组与数组行指针的使用*/
#include <stdio.h>
main( )
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p)[4], i, j;
/*(*p)[4]是定义一个指针变量 p 指向包含 4 个元素的一维数组,即行指针,
而不是指针数组,指针数组的定义是:*p[4]。注意它们的定义语法与含义不同。*/
p=a; /*p指向数组的行*/
for(i=0;i<3;i++){
for(j=0;j<4;j++)
printf("a[%d,%d]=%d\t", i, j, *(*(p+i)+j) );
printf("\n");
}
}
#include <stdio.h>
int main()
{
int a[5], i;
printf("Input five numbers:");
for (i=0; i<5; i++)
{
//scanf("%d", &a[i]); /* 用下标法引用数组元素 */
scanf("%d", a+i); /* 用指针法引用数组元素 */
}
for (i=0; i<5; i++)
{
//printf("%2d", a[i]); /* 用下标法引用数组元素 */
printf("%2d", *(a+i)); /* 用指针法引用数组元素 */
}
printf("\n");
return 0;
}
#include <stdio.h>
void InputArray(int a[], int n);
void OutputArray(int a[], int n);
int main()
{
int a[5];
int *p = a;
printf("Input five numbers:");
InputArray(p, 5); /* 用指向一维数组的指针变量作为函数实参 ,p是数组首地址,相当于传过去了a的首地址*/
OutputArray(p, 5); /* 用指向一维数组的指针变量作为函数实参 */
return 0;
}
//形参声明为数组
//void InputArray(int a[], int n) /* 形参声明为数组,输入数组元素值 */
//{
// int i;
// for (i=0; i<n; i++)
// {
// scanf("%d", &a[i]); /* 用下标法访问数组元素 */
// }
//}
//void OutputArray(int a[], int n) /* 形参声明为数组,输出数组元素值 */
//{
// int i;
// for (i=0; i<n; i++)
// {
// printf("%4d", a[i]); /* 用下标法访问数组元素 */
// }
// printf("\n");
//}
//形参声明为指针变量
void InputArray(int *pa, int n) /* 形参声明为指针变量,输入数组元素值 */
{
int i;
for (i=0; i<n; i++, pa++)
{
scanf("%d", pa); /* 用指针法访问数组元素 */
}
}
void OutputArray(int *pa, int n) /* 形参声明为指针变量,输出数组元素值 */
{
int i;
for (i=0; i<n; i++, pa++)
{
printf("%4d", *pa); /* 用指针法访问数组元素 */
}
printf("\n");
}
#include <stdio.h>
#define N 4
void InputArray(int p[][N], int m, int n);
void OutputArray(int p[][N], int m, int n);
int main()
{
//二维数组写法
int a[3][4];
printf("Input 2*2 numbers:\n");
InputArray(a, 2, 2); /* 向函数传递二维数组的第0行的地址 */
OutputArray(a, 2, 2); /* 向函数传递二维数组的第0行的地址 */
return 0;
//行指针代表二维数组写法
// int a[2][2];
// int (*p)[2];
// p=a;/*或者p=&a[0]*/
// printf("Input 2*2 numbers:\n");
// InputArray(p, 2, 2); /* 向函数传递二维数组的第0行的地址 */
// OutputArray(p, 2, 2); /* 向函数传递二维数组的第0行的地址 */
// return 0;
//列指针写法,看做4个元素的一维数组
// int a[2][2];
// int *p;
// p=a;/*或者p=&a[0]*/
// printf("Input 2*2 numbers:\n");
// InputArray(p, 2, 2); /* 向函数传递二维数组的第0行的地址 */
// OutputArray(p, 2, 2); /* 向函数传递二维数组的第0行的地址 */
// return 0;
}
/* 形参声明为列数已知的二维数组,输入数组元素值 */
//void InputArray(int p[][N],int m, int n)
/* 形参声明为指向二维数组的列指针,输入数组元素值 */
//void InputArray(int *p, int m, int n)
/* 形参声明为指向列数已知的二维数组的行指针,输入数组元素值 */
void InputArray(int (*p)[N], int m, int n)
{
int i, j;
for(i = 0; i<m; i++)
{
for(j = 0; j<n; j++)
{
scanf("%d", &p[i][j]);
}
}
}
/* 形参声明为列数已知的二维数组,输出数组元素值 */
//void OutputArray(int p[][N], int m, int n)
/* 形参声明为指向二维数组的列指针,输出数组元素值 */
//void OutputArray(int *p, int m, int n)
/* 形参声明为指向列数已知的二维数组的行指针,输入数组元素值 */
void OutputArray(int (*p)[N], int m, int n)
{
int i, j;
for(i = 0; i<m; i++)
{
for(j = 0; j<n; j++)
{
printf("%4d", p[i][j]);
}
printf("\n");
}
}
#include <stdio.h>
#include <string.h>
#define MAX_LEN 10 /* 字符串最大长度 */
#define N 150 /* 字符串个数 */
void SortString(char *ptr[], int n);
int main()
{
int i, n;
char name[N][MAX_LEN]; /* 定义二维字符数组 */
char *pStr[N]; /* 定义字符指针数组 */
printf("How many countries?");
scanf("%d", &n);
getchar(); /* 读走输入缓冲区中的回车符 */
printf("Input their names:\n");
for (i=0; i<n; i++)
{
pStr[i] = name[i]; /* 让pStr[i]指向二维字符数组name的第i行 */
gets(pStr[i]); /* 输入第i个字符串到pStr[i]指向的内存 */
}
SortString(pStr, n); /* 字符串按字典顺序排序 */
printf("Sorted results:\n");
for (i=0; i<n; i++)
{
puts(pStr[i]); /* 输出排序后的n个字符串 */
}
return 0;
}
/*函数功能:用指针数组作函数参数,采用交换法实现字符串按字典顺序排序 */
void SortString(char *ptr[], int n)
{
int i, j;
char *temp = NULL; /* 因交换的是字符串的地址值,故temp定义为指针变量 */
for (i=0; i<n-1; i++)
{
for (j = i+1; j<n; j++)
{
if (strcmp(ptr[j], ptr[i]) < 0) /* 交换指向字符串的指针 */
{
temp = ptr[i];
ptr[i] = ptr[j];
ptr[j] = temp;
}
}
}
}
#include <stdio.h>
#include <stdlib.h>
void InputArray(int *p, int n);
double Average(int *p, int n);
int main()
{
int *p = NULL, n;
double aver;
printf("How many students?");
scanf("%d", &n); /* 输入学生人数 */
p = (int *) malloc(n * sizeof(int)); /* 向系统申请内存 */
if (p == NULL) /* 确保指针使用前是非空指针,当p为空指针时结束程序运行 */
{
printf("No enough memory!\n");
exit(1);
}
printf("Input %d score:", n);
InputArray(p, n); /* 输入学生成绩 */
aver = Average(p, n); /* 计算平均分 */
printf("aver = %.1f\n", aver); /* 输出平均分 */
free(p); /* 释放向系统申请的内存 */
return 0;
}
/* 形参声明为指针变量,输入数组元素值 */
void InputArray(int *p, int n)
{
int i;
for (i=0; i<n; i++)
{
scanf("%d", &p[i]);
}
}
/* 形参声明为指针变量,计算数组元素的平均值 */
double Average(int *p, int n)
{
int i, sum = 0;
for (i=0; i<n; i++)
{
sum = sum + p[i];
}
return (double)sum / n;
}
当然合法。在声明形式参数时,不管 a 的元素是什么,*a 的写法和 a[]的写法总是一样的。
动态内存分配 (Dynamic Memory Allocation )是指在程序运行时为变量分配内存的一种方法
动态数组 (Dynamically Allocated Array )是指在程序中不事先指定数组的大小,在程序运行过程中确定数组的大小。使用动态数组的优点是可以根据用户需要,有效利用存储空间。
使用动态内存分配函数实现有n个 int型元素的一维动态数组,可使用
p = (int *) malloc(n * sizeof(int)); /* 向系统申请内存 */
if (p == NULL) /* 确保指针使用前是非空指针,当 p 为空指针时结束程序运行 */
{
printf("No enough memory!\n");
exit(1);
}
p = (int *) calloc(n, sizeof(int)); /* 向系统申请内存 */
if (p == NULL) /* 确保指针使用前是非空指针,当 p 为空指针时结束程序运行 */
{
printf("No enough memory!\n");
exit(1);
}
使用动态内存分配函数实现有m*n 个 int型元素的二维动态数组,可使用
p = (int *)calloc(m*n, sizeof(int)); /* 向系统申请内存 */
if (p == NULL) /* 确保指针使用前是非空指针,当 p 为空指针时结束程序运行 */
{
printf("No enough memory!\n");
exit(1);
}
int *a[3];
a = (int*) malloc(sizeof(int)*3);
free(a);
问题解答
int *a[3];定义的是指针数组,所以不能为a从新分配内存。
虽然一些程序员都这样做,但不是真的有什么好处,强制类型转换这些函数返回 void *型的指针并不是标准 C 必需的,因为 void *型的指针会在赋值操作时自动转换为任何指针类型。对返回值进行强制类型转换的习惯来自于经典 C。在经典 C 中,内存分配函数返回char *型的值,用强制类型转换实现是必要的。
void*指针是 ANSI C 新标准中增加的一种指针类型,具有一般性,通常称为通用指针(Generic Pointer),常用来说明其基类型未知的指针,即声明了一个指针变量,但未指定它可以指向哪一种基类型的数据。因此,若要将函数调用的返回值赋予某个指针,则应先根据该指针的基类型,用强转的方法将返回的指针值强转为所需的类型,然后再进行赋值操作。
因篇幅问题不能全部显示,请点此查看更多更全内容