0%

C语言指针

指针

1
2
3
4
5
6
7
8
int *p; P是一个返回整型数据的指针 
int p[3]; P 是一个由整型数据组成的数组
int *p[3]; 数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组
int (*p)[3]; P 是一个指针,指向的内容是一个数组,然后再与int结合,说明数组里的元素是整型的,所以P 是一个指向由整型数据组成的数组的指针

int (*p)(int); P 是一个指针,指向的是一个函数,函数有一个int 型的参数,函数的返回类型是整型,P 是一个指向有一个整型参数且返回类型为整型的函数的指针

int *(*p(int))[3]; 从P 开始,先与()结合,说明P 是一个函数,然后进入()里面,与int 结合,说明函数有一个整型变量参数,然后再与外面的*结合,说明函数返回的是一个指针,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与*结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P 是一个参数为一个整数据且返回一个指向由整型指针变量组成的数组的指针变量的函数.

指针和数组、字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
char *p = "abc";
p[0] = 'd'; //不能修改指针
printf("%s", p); //错误

char p[] = "abc";
p[0] = 'd'; //可以修改数组
printf("%s", p); //dbc


把另一个数组中每个元素的地址赋给指针数组的每个元素。
int *a[5], b[] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
a[i] = &b[i];


char *c[4] = {"if", "else", "for", "while"};
for (int i = 0; i < 4; i++) //需要先确定数组元素个数
puts(c[i]); //输出c[i]所指字符串

char *c[] = {"if", "else", "for", "while", NULL};
for (int i = 0; c[i] != NULL; i++)
puts(c[i]);


char *a[5] = {"abcd", "efghi"};
char **p = a;
printf("%c\n", *(*(p + 1) + 2)); //g
printf("%c\n", *(p[1] + 2)); //g
printf("%s\n", p[1]); //efghi
printf("%s\n", *(p + 1)); //efghi


int a[4][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int (*p)[4] = a;
printf("%d\n", *(*(p + 1) + 1)); //6
printf("%d\n", *(p[1] + 1)); //6

char str[][10] = {"qaz", "wsx", "edc"};
char (*s)[10] = str;
printf("%s\n", s); //qaz
printf("%s\n", s[0]); //qaz
printf("%c\n", s[1][1]); //s
printf("%s\n", s[1] + 1); //sx
printf("%s\n", *(s + 1)); //wsx
printf("%c\n", *(*(s + 1) + 1)); //s


难点!&a和a; 数组名 a 可以作数组的首地址,而&a 是数组的指针。
int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int *)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1)); //2,5

int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int *)(a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1)); //2,1

分配内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
分配动态二维数组的内存空间,使用完后清除动态数组的内存空间
int **canvas = (int **)malloc(high * sizeof(int *));
for (i = 0; i < high; i++)
canvas[i] = (int *)malloc(width * sizeof(int));

for (i = 0; i < high; i++)
free(canvas[i]);
free(canvas);


为矩阵动态分配内存的函数
int **Create(int m, int n)
{
int **Matrix;
Matrix = (int **)malloc(sizeof(int *) * m);
for (int i = 0; i < m; i++)
Matrix[i] = (int *)malloc(sizeof(int) * n);

return Matrix;
}
读入数据函数
void Input(int **Matrix, int m, int n)
{
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
fscanf(fp, "%d", &Matrix[i][j]);
}


重点!为指针数组申请空间
int main()
{
//新建一维数组,arr指向4个元素的数组
int *arr = (int *)malloc(sizeof(int) * 4);
for (int i = 0; i < 4; i++)
{
arr[i] = i * i; //*(arr+i)=i*i;
printf("%d\t", arr[i]);
}
free(arr);

int **p; //新建二维数组 8*10
p = (int **)malloc(sizeof(int *) * 8); //新建行指针
for (int i = 0; i < 8; i++)
p[i] = (int *)malloc(sizeof(int) * 10); //p[i]是指针,指向i行第一个元素
free(p);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
输出string
void put1(const char *string)
{
while (*string) // same as *string != '\0'
putchar(*string++);
}

字符输出
while (*p != '\0')
{
printf("%c", *p++);
Sleep(45);
}
字符串输出
if (p != NULL)
{
printf("%s", p);
Sleep(45); //Sleep没有效果,直接输出字符串
}
1
2
3
4
5
6
7
8
字符串长度
int length(char *p)
{
int n = 0;
while (*p++ != '\0')
n++;
return n;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
注意指向。复制或者写入到某一字符串,需要注意空间是否足够!!!!
char *mystrcat(char *str1, char *str2) //连接两个字符串
{
char *p = str1; //要有一个中间量
while (*str1 != '\0') //先读到
str1++;
while (*str2 != '\0') //加到第一个字符串的最后
*str1++ = *str2++;
*str1 = '\0';
//str1已经指向了最后, 不能直接返回str1
return p; //p指向str1的开头
}
char *mystrcpy(char *str1, char *str2)
{
char *p = str1;
while (*str2 != '\0')
*str1++ = *str2++; //复制到第一个字符串
*str1 = '\0';
return p;
}
int main(void)
{
char s1[50] = "we are ";
char s2[] = "friends !";

char *s3 = mystrcat(s1, s2); //连接两个字符串,返回指针
printf("\ns3=%s", s3); //we are friends !

char *s5 = s3;
char *s4 = mystrcpy(s1, s2); //复制到第一个字符串,返回指针
printf("\ns4=%s", s4); //friends !
printf("\ns5=%s", s5); //friends !
//s5不等于 s3
//有这种情况是因为,s5=s3,s3=p,p=str1,str1=s1,
//所以s3一直指向s1; s1被mystrcpy()改变了,s5也变了,
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
删除字符串里的某个字符
void delet(char *p, char c)
{
char *q, *w; //使用两个中间指针
while (*p != '\0')
{
if (*p == c)
{
q = p;
w = q + 1;
while (*w != '\0')
*q++ = *w++;
*q = '\0';
}
p++;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void CopyString(char **dest, char *source, int m)
/*将字符串source中的第m个以后的字符复制到dest中*/
{
int n = strlen(source);
*dest = (char *)malloc(sizeof(n - m + 2));
for (int i = m - 1; source[i] != '\0'; i++)
((*dest)[i - m + 1]) = source[i];
*(*dest + n - m + 2) = '\0';
}
void Copy(char *&dest, char *source, int m)
/*将字符串source中的第m个以后的字符复制到dest中*/
{
int n = strlen(source);
dest = (char *)malloc(sizeof(n - m + 2));
for (int i = m - 1; source[i] != '\0'; i++)
dest[i - m + 1] = source[i];
dest[n - m + 2] = '\0';
}
int main()
{
int m = 3, a[N];
char *source = "Hello DataStructure!", *dest;
CopyString(&dest, source, m);
printf("将source中的第%d个以后的字符复制到dest后,dest的内容是:\n", m);
printf("%s\n", dest);

char *des;
Copy(des, source, m);
printf("将source中的第%d个以后的字符复制到dest后,dest的内容是:\n", m);
printf("%s\n", des);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
字符串比较
int strcmp2(const char *dest, const char *source)
/*如果dest的值大于source,则返回值大于0;如果dest的值等于source,则返回值等于0;如果dest的值小于source ,则返回值小于0*/
{
if ((dest != NULL) && (source != NULL))
return 0;

while (*dest != '\0' && *source != '\0' && (*dest == *source))
{
source++;
dest++;
}
return *dest - *source;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
字符串转数字
int ascii_to_integer(char *string)
{
int digit, value = 0;
while (*string >= '0' && *string <= '9')
{
value *= 10;
value += *string - '0';
string++;
}

if (*string != '\0')
value = 0;
return value;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
判断一字符串是否为回文,是返回1,不是返回0,出错返回-1
int fun(char *p)
{
int len = strlen(p) - 1;
char *q = p + len; //p指向开头,q指向末尾
while (p < q)
if ((*p++) != (*q--))
return 0;
return 1;
}

int main(void)
{
char *p = "vbnvcnbv";
printf("%d", fun(p));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
字符串 两种方法
void GetMemory1(char **p)
{
*p = (char *)malloc(sizeof(char) * 100);
strcpy(*p, "Have a good day!");
}
char *GetMemory2(void)
{
char *p = "Have a good day!";
return p;
}
int main(void)
{
char *str1 = NULL;
GetMemory1(&str1);
char *str2 = GetMemory2();
printf("\nstr1:%s", str1);// "Have a good day!"
printf("\nstr2:%s", str2);// "Have a good day!"
free(str1);
}
1
2
3
4
5
6
7
8
9
10
11
字符串倒序,如“abcd”倒序后变为“dcba”
char *src = "hello,world ";
int len = strlen(src);
char *dest = (char *)malloc(len + 1); //要为\0分配一个空间
char *d = dest;
char *s = &src[len - 1]; //指向最后一个字符
while (len-- != 0)
*d++ = *s--; //s指向的值赋给d指向的
*d = 0; //尾部要加\0
printf("%s\n ", dest);
free(dest); // 使用完,应当释放空间,以免造成内存汇泄露
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
递归,倒序输出name。指针指到最后,再指回来
void DisplayNames(char **cNameArray) //二级指针
{
if (*cNameArray == "end")
printf("%s ", *cNameArray);
else
{
DisplayNames(cNameArray + 1); /*调用递归函数*/
printf("%s ", *cNameArray);
}
}
void Display(char **cNameArray) //二级指针
{
int i = 0;
char **p = cNameArray;
while (i++ < 6)
printf("%s ", *p++);

i = 0;
*p--;
while (i++ < 6)
printf("%s ", *p--);
}
int main()
{
char *cNames[] = {"Aaron", "Jim", "Charles", "Sam", "Ken", "end"};
//调用递归函数,倒序输出
DisplayNames(cNames);
//指针指到最后,再指回来
Display(cNames);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void sort(char *strings[], int n) /*自定义排序函数*/
{
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (strcmp(strings[i], strings[j]) > 0) /*比较两个字符串的大小*/
{
char *temp = strings[i];
strings[i] = strings[j];
strings[j] = temp; /*如果前面字符串比后面的大,则互换*/
}
}
int main()
{
char **p, *month[] = {"January(一月)", "February(二月)", "March(三月)", "April(四月)", "May(五月)", "June(六月)", "July(七月)", "August(八月)", "September(九月)", "October(十月)", "November(十一月)", "December(十二月)"};
p = month;
sort(p, 12);

for (int i = 0; i < 12; i++)
printf("%s\n", month[i]); /*输出排序后的字符串*/
return 0;
}

指针和函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
struct MyStruct
{
int a;
float f;
};
static struct MyStruct Func(struct MyStruct s, int a[])
{
printf("sum = %f\n", s.a + s.f + a[0]);
return s;
}
static void Test(void)
{
struct MyStruct s = {10, 0.5f};
int a[] = {1, 2, 3};
static struct MyStruct (*p)(struct MyStruct s, int a[]) = NULL;
p = Func;
p(s, a); // Func(s,a);
}
int main()
{
void (*pf)(void); //定义
pf = Test; //赋值
(*pf)(); //调用Test();

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char *fun1(char *p)
{
printf("%s\n", p);
return p;
}
int Function()
{
printf("Call Function!\n");
}
int main()
{
int (*p)();
//*(int *)&p = (int)Function;
p=&Function;
(*p)();//调用

char *(*pf[3])(char *p);
pf[0] = &fun1;
pf[0]("fun1");//调用

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef int (*PF)(int, int);

int add(int a, int b)
{
return a + b;
}
int reduce(int a, int b)
{
return a - b;
}
int main()
{
PF pfunc = NULL;
pfunc = add;
printf("add:%d\n", pfunc(3, 4));

pfunc = reduce;
printf("reduce:%d\n", pfunc(3, 4));

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
float Divide(float f1, float f2)
{
return f1 / f2;
}
float MathFunc(float (*p)(float, float), float para1, float para2)
{
return (*p)(para1, para2);
}
int main(void)
{
float a = 1, b = 2;
printf("\na/b=%f", MathFunc(Divide, a, b));
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef int(FUNC1)(int in);
typedef int(FUNC2)(int *, int *, int *);

int inc(int a)
{
return (++a);
}
int multi(int *a, int *b, int *c)
{
return (*c = *a * *b);
}
void show(FUNC2 fun, int arg1, int *arg2)
{
FUNC1 *p = &inc;
int temp = p(arg1);
fun(&temp, &arg1, arg2);
printf("%d\n", *arg2);
}
int main(void)
{
int a;
show(multi, 10, &a);//110
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static int sArray[3] = {1, 4, 8};

static int *Func1(int a)
{
printf("Func1 a = %d\n", a);
return sArray; //首元素;
}
// 定义了Func2函数,其类型为:int (* (int, float) )[3],
// 表示该函数返回类型为int (*) [3],形参列表具有两个参数,第一个形参a具有int类型,
// 第二个形参f具有float类型
static int (*Func2(int a, float f))[3]
{
printf("Func2 sum = %f\n", a + f);
return &sArray;
}
int main()
{
const int *p = Func1(3);
printf("*p = %d\n", *p);

// 这里声明了一个指针对象pFunc,它指向函数Func2
int(*(*pFunc)(int, float))[3] = &Func2;
pFunc(3, 10.5f)[0][1]++;

int elem = sArray[1];
printf("elem = %d\n", elem);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void func(int a)
{
printf("a = %d\n", a);
}
static void (* MyFunc(float f) )(int)
{
printf("f = %f\n", f);
return &func;
}
int main()
{
void (*pArray[3])(int) = { NULL };
// pp指向pArray数组对象,其类型为:void (* (*)[3])(int)
// 注意,这里最里面的(*)两旁的()不可省
void (*(*pp)[3]) (int) = &pArray;
pp[0][1] = &func;
(*pp)[1](10);
void (* (*pFunc) (float) ) (int) = &MyFunc;
pFunc(2.5f)(20);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
static int sArray[] = {1, 2, 3};

static void Func1(int a)
{
printf("f1 a = %d\n", a);
}
static void Func2(int a)
{
printf("f2 a = %d\n", a);
}
static void Func3(int a, int b)
{
printf("b - a = %d\n", b - a);
}
static void func(int a)
{
printf("a = %d\n", a);
}
static int (*Fun(void))[3]
{
return &sArray;
}

int main()
{
void (*arr[3])(int) = {&func};
//pArray的类型为指向一个含有3个元素的数组的指针,
void (*(*pArray)[3])(int) = &arr;
pArray[0][0](100);

int(*(*pFunc)(void))[3] = &Fun;
// 由于pFunc所指函数的返回类型是int (*)[3],所以pFunc()[0]则是int[3],
// 这里的pFunc()[0]与(*pFunc())是等价的
int *p = pFunc()[0];
printf("Sum is: %d\n", p[0] + p[1] + p[2]);
// 即指向返回类型为void,带有一个int类型形参的函数的指针的指针
void (**array[3])(int) = {&arr[0]};
// 通过array数组对象做函数调用
(*array[0])(10);

//注意和上面的区别
// void (*pFuncs[2])(int) ={ &Func1, &Func2 };//2个函数
//或者,如下
void (*pFuncs[2])(int);
pFuncs[0] = &Func1;
pFuncs[1] = &Func2;

int i = 0;
pFuncs[i](i + 1);
i++;
pFuncs[i](i + 1);
i++;
Func3(i, i + 1);
i++;

i = 0;
int j = 0;
// 由于i与j是两个不同的对象,因此这里不会引发顺序点的冲突问题
pFuncs[j++](++i);
pFuncs[j++](++i);
Func3(j, ++i);

return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
double t(double a, double (*p)(double))
{
return (*p)(a * a);
}
double f(double x)
{
return 2.0 * x;
}
double g(double x)
{
return 2.0 + x;
}
int main()
{
double x = 4.0;
printf("u=%5.3f,v=%5.3f\n", t(x, f), t(x, g)); //32.0 18.0
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
float Plus(float f1, float f2)
{
return f1 + f2;
}
float Minus(float f1, float f2)
{
return f1 - f2;
}
float Multiply(float f1, float f2)
{
return f1 * f2;
}
float Divide(float f1, float f2)
{
return f1 / f2;
}
float MathFunc(float (*p)(float, float), float para1, float para2)
{
return (*p)(para1, para2);
}
int main(void)
{
float a = 1.5, b = 2.5;
printf("\na+b=%f", MathFunc(Plus, a, b));
printf("\na-b=%f", MathFunc(Minus, a, b));
printf("\na*b=%f", MathFunc(Multiply, a, b));
printf("\na/b=%f", MathFunc(Divide, a, b));
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
float max(float x, float y)
{
return x > y ? x : y;
}
void TianFunc()
{
printf("Tian ");
}
void YaFunc()
{
printf("Ya!\n");
}
int main()
{
void (*funcp)() = TianFunc;
//funcp = TianFunc;
(*funcp)();
funcp = YaFunc;
(*funcp)();

float a = 1, b = 2, c;
float (*p)(float x, float y);
p = max;
c = (*p)(a, b);
printf("\nmax=%f", c);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int *Address(int (*ptrScore)[4], int n)
{
int *p = *(ptrScore + n);
return p;
}
void Display(int a[][4], int n, int *p)
{
for (int i = 0; i < n; i++)
printf("%4d", *(p + i));
printf("\n");
}
int main()
{
int row, n = 4, *p;
int score[3][4] = {{76, 87, 85, 81}, {67, 61, 71, 60}, {81, 89, 82, 78}};
printf("请输入学生的编号(1或2或3).输入0退出程序.\n");
scanf("%d", &row);
while (row)
{
if (row == 1 || row == 2 || row == 3)
{
printf("第%d个学生的成绩4门课的成绩是:\n", row);
p = Address(score, row - 1);
Display(score, n, p);
printf("请输入学生的编号(1或2或3).输入0退出程序.\n");
scanf("%d", &row);
}
else
{
printf("输入不合法,重新输入(1或2或3).输入0退出程序.\n");
scanf("%d", &row);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int *search(int (*point)[4], int n)
{
int *pt = *(point + n);
return pt; //返回某一行
}
int main(void)
{
int score[][4] = {{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 9, 9, 9}};
int *p = search(score, 1); //p指向某一行;
for (int i = 0; i < 4; i++)
printf("%d\t", *(p + i)); //某一行的元素

return 0;
}