数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量。
int a = 1;
int *p = &a;
通过指针变量p获取数据:
printf("%d", *P);
1)表示乘法,例如int a = 1, b = 2, c; c = a * b;,这是最容易理解的
2)表示定义一个指针变量,以和普通变量区分开,例如int a = 100; int *p = &a;
3)表示获取指针指向的数据,是一种间接操作,例如*p = 100; b = *p;
Array是一系列具有相同类型的数据的集合,每一份数据叫Element(数组元素)。数组中的所有元素在内存中是连续排列的。
如:
int arr[] = {1,2,3,4,5,6};
定义数组时,要给出数组名和数组长度,数组名可以认为时一个指针,它指向数组的第0个元素。
*(arr + 1) 获取的数据和arr[1]等价
arr本身是一个指针,可以直接赋值给指针变量p:
int *p = arr;
*p++ 等价于*(p++),表示先取得第n个元素的值,再将p指向下一个元素
*++P 等价于*(++p),会先进行++p运算,使得p的值增加,指向下一个元素,整体上相当于*(p+1)
(*p)++ 等价于对指针变量p获取的数值做加1操作。
c语言没有特定的字符串类型,我们通常时将字符串放在一个字符数组中。
int main()
{
char str[] = "Say Hello!";
int len = strlen(str);
printf("%s\n", str);
for(int i = 0; i < len; i++){
printf("%c", str[i]);
}
}
指针和数组的规则同样也适用于字符数组:
int main()
{
char *str = "Say Hello!";
int len = strllen(str);
printf("%s\n", str);
for(int i = 0; i < len; i++){
printf("%c", str[i]);
//使用*(str + i)
printf("%c", *(str + i));
}
}
C语言有两种表示字符串的方法,
1)是字符数组:字符数组存储在全局数据区或栈区,使得字符数组可以读取和修改
char str[] = "Say Hello!";
str = "you you!"; //正确
str[1] = 'A' //正确
2)是字符串常量:字符串存储在常量区,只能读取不能修改
char *str = "Say Hello!";
str = "you you!"; //正确,可以更改指针变量本身的指向。
str[1] = 'A'; //错误,不能对常量进行写入。
*(str + 1) = 'A'; //错误,不能对常量进行写入。
#include
void swap(int *p1, int *p2){
int temp; //临时变量
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main(){
int a = 1, b = 2;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。
int *max(int *a, int *b)
{
if (*a > *b) {
return a;
}
else{
return b;
}
}
int main()
{
int a = 10;
int b = 20;
int *c = max(&a, &b);
printf("max num is %d\n", *c);
}
int main()
{
int a = 1;
int *p1 = &a;
int **p2 = &p1;
printf("%d, %d, %d", a, *p1, **p2);
}
解析:*p2指向的是指针变量p1的值,**p2是指针变量p1的获取数据的值(*p1)
如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。
int main()
{
//整形指针数组
int a = 1, b = 2, c = 3;
//定义一个指针数组
int *arr[3] = {&a, &b, &c}; //可以不指定长度
//定义一个指向指针数组的指针
int **parr = arr;
printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]);
printf("%d, %d, %d\n", **(parr+0), **(parr+1), **(parr+2));
//字符串数组和指针数组
char *str[3] = {
"hello one!",
"hello two!",
"hello three!"
}
printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
//字符串指针数组
char *str0 = "hello one!";
char *str1 = "hello two!";
char *str2 = "hello three!";
char *str[3] = {str0, str1, str2};
printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
return 0;
}
int main()
{
int a[2][2] = {{1,2}, {3,4}};
//定义一个指向a的指针变量p;
int (*p)[2] = a; //括号中*表明p是一个指针,它指向一个数组。[]的优先级高于*,所以()是必须要加的。如果写成*p[2]就成指针数组了。
printf("%zu\n", sizeof(*(p+1)));
int i,j;
for(i=0; i<2; i++){
for(j=0; j<2; j++)
printf("%2d ",*(*(p+i)+j));
//printf("%2d ", (*(p + i))[j]);
printf("\n");
}
return 0;
}
一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。
#include
//返回两个数中较大的一个
int max(int a, int b){
return a>b ? a : b;
}
int main(){
int a = 1, b = 2;
//定义函数指针
int (*pmax)(int a, int b) = max;
int maxFunc = (*pmax)(a, b);
printf("maxFunc: %d\n", maxFunc);
return 0;
}
pmax 是一个函数指针,在前面加 * 就表示对它指向的函数进行调用
下一篇:(四)学习笔记 c语言基础 结构体
上一篇:(二)学习笔记 c语言基础 数据类型