目录
一、数组指针
本质是指针,指向数组
格式:
存储类型 数据类型 (*指针变量名)[列数]
int a[2][3] = {2,3,4,5,6,7};
int (*p)[3] = a;
printf("%p\n",*a); //0x7fffffffdda0
printf("%p\n",*a+1); //0x7fffffffdda4
printf("%p\n",p); //0x7fffffffdda0
printf("%p\n",p+1); //0x7fffffffddac
printf("%p\n",*a); //0x7fffffffdda0
printf("%p\n",*a+1); //0x7fffffffdda4
printf("%p\n",*p); //0x7fffffffdda0
printf("%p\n",*p+1); //0x7fffffffdda4
printf("%p\n",*(p+1)); //0x7fffffffddac
printf("%p\n",*(p+1)+1); //0x7fffffffddb0
地址 | 元素 | ||||
p[0] | p | *p | 2 | **p | *p[0] |
p[0]+1 | *p+1 | 3 | *(*p+1) | *(p[0]+1) | |
p[0]+2 | *p+2 | 4 | *(*p+2) | *(p[0]+2) | |
p[1] | p+1 | *(p+1) | 5 | **(p+1) | *p[1] |
p[1]+1 | *(p+1)+1 | 6 | *(*(p+1)+1) | *(p[1]+1) | |
p[1]+2 | *(p+1)+2 | 7 | *(*(p+1)+2) | *(p[1]+2) |
a和p本质不同,a是地址常量,不能为左值;p是指针变量。
访问二维数组元素的地址:i行j列
*(p+i)+j p[i]+j
访问二维数组元素的值:i行j列
*(*(p+i)+j) *(p[i]+j)
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a[3][4] = {};
int (*p)[4] = a,i,j;
for ( i = 0; i < 3; i++)
{
for ( j = 0; j < 4; j++)
{
scanf("%d",*(p+i)+j);//p[i]+j
}
}
for ( i = 0; i < 3; i++)
{
for ( j = 0; j < 4; j++)
{
printf("%d ",*(*(p+i)+j));//*(p[i]+j)
}
putchar(10);
}
return 0;
}
二、指针数组
本质是数组,数组中存储地址
格式:
存储类型 数据类型 *数组名[元素个数];
打印20:
int a = 10, b = 20, c = 30;
int *arr[3] = {&a,&b,&c};
=====================================
printf("%d %d %d\n",*arr[1],*(*arr+1),*(arr[0]+1)); //20 20 20
*arr[1]: arr[1]访问数组中第二个元素内容(&b),再加*,取内容(*&b)
*(arr[0]+1):arr[0]数组的第一个元素,+1到了第二个元素,再加*取内容
*(*(arr+1)):arr数组名是第一个元素的地址,arr+1是指针数组的第二个元素的地址,加*取指针数组的第二个元素的内容(&b),加*取变量的值
存放二维数组每一行第一列的地址
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int *p[3]={a[0],a[1],a[2]};
===================================
例*p[1]: 指针数组的第二个元素(a[1]二维数组的第二行第一列的地址);加*取内容
===================================
*p[1]: 指针数组的第二个元素(a[1]二维数组的第二行第一列的地址);加*取内容
打印6:
===================================
printf("%d %d %d\n",*(p[1]+1),*(*(p+1)+1),p[1][1]); //6 6 6
访问 a[1][2]地址:二维数组第二行第三列
//p[1]+2:p[1]:指针数组的第二个元素(==a[1]地址==a[1][0]地址), p[1]+2(a[1][2])
//*(p+1)+2:p+1:指针数组的第二个元素的地址,*(p+1)加*取针数组的第二个元素的内容(==a[1]地址==a[1][0]地址), *(p+1)+2
printf("%p %p\n",p[1]+2,*(p+1)+2);
访问 a[1][2]的值:*(p[1]+2)
*(*(p+1)+2)
printf("%d %d\n",*(p[1]+2),*(*(p+1)+2));
存放字符串首地址
char *a[3] = {"hello", "world", "sheep"};
打印“world”:
printf("%s %s \n", a[1], *(a + 1));
打印 “d”:
printf("%c %c \n", *(a[1] + 4), *(*(a + 1) + 4));
*(a[1]+4): a[1]指针数组的第二个元素(world的首地址),a[1]+4('d'地址)
*(*(a+1)+4) :a+1:指针数组的第二个元素的地址,加*取指针数组的第二个元素的内容(world的首地址)*(a+1)+4==>('d'地址)
a[1][4]
命令行参数
argv :指针数组,存放命令行传递的字符串
argc :命令行传递的字符串的个数
#include<stdio.h>
int main(int argc, char const *argv[])
{
printf("%s\n",argv[1]);
printf("%d\n",argc);
return 0;
}
三、函数
功能、参数、返回值
格式
数据类型 函数名(形式参数1,形式参数2……)
{
//函数体
}
函数的声明
使用条件:当函数写在主函数下边,需要提前声明
数据类型 函数名(形式参数1,形式参数2……);
格式:
数据类型需要和返回值数据类型一致;如果没有返回值,数据类型用void
1. 不需要参数,不需要返回值:
void fun()
{
printf("fat sheep -w-");
}
int main() //程序入口
{
fun(); //函数调用
return 0;
}
2. 不需要返回值,需要参数
void fun(int n1,int n2)
{
int sum=n1+n2;
printf("%d\n",sum);
}
int main(int argc, char const *argv[])
{
int a=5,b=9;
fun(8,9);
fun(a,b);
return 0;
}
3. 需要返回值,需要参数
int fun(int n1,int n2); //先声明
int main(int argc, char const *argv[])
{
int a=5,b=9;
int res = fun(8,9);
fun(a,b);
printf("res:%d\n",res);
return 0;
}
int fun(int n1,int n2)
{
int sum=n1+n2;
printf("%d\n",sum);
return sum;
}