C语言-指针数组与数组指针

一. 指针数组

指针数组:数组里面存放的都是指针变量。

本质,是一个数组。 数组中数据元素是 指针。指针是字符类型指针,用的多。

cpp 复制代码
数据类型 *数组名[整型常量]
cpp 复制代码
char* a[4]={NULL};//初始化方法
char * b[5]={"hello","ok","how","are","you"}; // 指针指向了字符串常量去,只可以读取,不
可以修改

char str[8][100]={"hello","ok","how","are","you"};
char *str3[5]={str[0],str[1],str[3]};// 指针指向了数组,可以读取,可以修改

存放字符串使用字符数组,操作字符串使用指针。

存放多个字符串使用二维字符数组(多个字符串的话)。操作字符串数组使用 指针数组

cpp 复制代码
//冒泡排序
void bubble_sort(char **ppstr, int size)
{
    int i = 0, j = 0;
    for(i = 1; i < size; i++)
    {
        for(j = 0; j < size - i; j++)
        {
            if(strcmp(ppstr[j],ppstr[j+1]) > 0)
            {
                //只是交换指针内部存储的地址
                char *temp = ppstr[j];
                ppstr[j] = ppstr[j+1];
                ppstr[j+1] = temp;
            }
        }
    }
}
//打印
void print(char **pptr,int size)
{
    int i = 0;
    for(i = 0;i < size; i++)
    {
        printf("%d %s\n",i,*(pptr + i));
    }
}

//分割字符串
int main()
{   
    char str[100] = "how are you";
    char *pstr[3] = {NULL};
    int size = sizeof(pstr) / sizeof(pstr[0]);
    char *temp = str;
    pstr[0] = str;
    int i = 1;
    while(*temp)
    {
        if(*temp == ' ')
        {
            *temp = '\0';
            pstr[i++] = temp+1;
        }
        temp++;
    }
    print(pstr, size);
    bubble_sort(pstr, size);//对其进行冒泡排序
    print(pstr, size);

    return 0;
}

结果:

二. 数组指针

数组指针:对一个一维数组进行&操作,地址值不变,类型升级为指向整个数组的指针。

对数组指针执行解引用操作 (*) , 地址值不变, 类型降为指向第一个元素的指针。

应用:需要同二维数组配合使用。

把二维数组作为参数传参的时候,在被调函数中参数的数据类型会使用到。

数组名:数组名在大多数情况下都表示数组首元素的地址。下面两种情况例外:

1、sizeof(数组名):这里数组名表示整个数组的大小,计算的是整个数组的大小。

2、&数组名:表示取出整个数组的地址,加1跳过整个数组的大小。

注:情况一必须是数组名单独放在sizeof里面才可以:

cpp 复制代码
int a[5] = { 0 };
    printf("sizeof(a) is %lu\n",sizeof(a));
    printf("sizeof(a + 1) is %lu\n",sizeof(a + 1));//这里a表示的是
                                                   //首元素的地址

结果:

cpp 复制代码
    int a[5] = {1,2,3,4,5};
    printf("a addr is %p\n",a);
    printf("a[0] addr is %p\n",&a[0]);
    printf("a[1] addr is %p\n",&a[1]);

    printf("*(a+1)  is %d\n",*(a+1));
    printf("a[1]  is %d\n",a[1]);
    
    printf("&a is %p\n",&a);
    printf("&a+1 is %p\n",&a+1);

    int (*pa)[5] = &a;//数组指针

三. 二级指针

二级指针:指向指针的指针。 在定义指针变量的时候,会开辟8个自己的空间 。指针变量本身也是有内存地址的。

对一级指针取地址操作,就会获得二级指针。

需要解引用两次 ,可以访问到数数据。

应用:

1). 如果在被调函数中,需要修改指针的指向(指针本身)。,就需要传递二级指针。

2) 如果在被调函数中,需要修改指针指向的内容(指针指向的变量数据)。,就需要传递一级指针

cpp 复制代码
int main()
{
    int a = 10;
    int *pa = &a;
    printf("a addr is %p\n",&a);
    printf("pa is %p\n",pa);
    printf("pa addr is %p\n",&pa);

    int **ppa = &pa;//二级指针
    printf("ppa is %p\n",ppa);
    printf("**ppa is %d\n",**ppa);

    return 0;
}

四. 有关指针的练习题

cpp 复制代码
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));

结果:2,5

cpp 复制代码
struct Test//这个结构体大小为20字节
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p//假设p是0x100000

printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);

结果:0x100014 0x100001 0x100004

cpp 复制代码
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( "%x,%x", ptr1[-1], *ptr2);

结果:4 2000000(大多计算机是小端存储)

cpp 复制代码
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);

结果:1

cpp 复制代码
int a[5][5];
int(*p)[4];
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);

结果: &p[4][2] - &a[4][2] 得到的是指针之间的元素个数(同一数组中,指针-指针得到的是指针之

间的元素个数) 可知结果是-4,本题的关键点在打印的格式,以%d的格式打印出-4,若以

%p的格式打印在打印出FFFFFFFC,因为地址没有原反补的概念,故直接打印出内存中的

值。

FFFFFFFC -4

cpp 复制代码
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);
int *ptr2 = (int *)(*(aa + 1));
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));

结果:10 5 (指针的类型决定了加减操作跳过的字节数)

cpp 复制代码
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);

结果:at

cpp 复制代码
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);

结果:POINT ER ST EW

cpp 复制代码
//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//16
printf("%d\n",sizeof(a+0));//一个地址4或者8
printf("%d\n",sizeof(*a));//4
printf("%d\n",sizeof(a+1));//一个地址4或者8
printf("%d\n",sizeof(a[1]));//4
printf("%d\n",sizeof(&a));//一个地址4或者8
printf("%d\n",sizeof(*&a));//16
printf("%d\n",sizeof(&a+1));//一个地址4或者8
printf("%d\n",sizeof(&a[0]));//一个地址4或者8
printf("%d\n",sizeof(&a[0]+1));//一个地址4或者8
cpp 复制代码
//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//48
printf("%d\n",sizeof(a[0][0]));//4
printf("%d\n",sizeof(a[0]));//16   a[0]表示第0行,类型:int [4]
printf("%d\n",sizeof(a[0]+1));//一个地址4或者8
printf("%d\n",sizeof(*(a[0]+1)));//4
printf("%d\n",sizeof(a+1));//一个地址4或者8
printf("%d\n",sizeof(*(a+1)));//16
printf("%d\n",sizeof(&a[0]+1));//一个地址4或者8
printf("%d\n",sizeof(*(&a[0]+1)));//16
printf("%d\n",sizeof(*a));//16
printf("%d\n",sizeof(a[3]));//16
cpp 复制代码
char *p = "abcdef";
printf("%d\n", sizeof(p));//一个地址4或者8
printf("%d\n", sizeof(p+1));//一个地址4或者8
printf("%d\n", sizeof(*p));//1
printf("%d\n", sizeof(p[0]));//1
printf("%d\n", sizeof(&p));//一个地址4或者8
printf("%d\n", sizeof(&p+1));//一个地址4或者8
printf("%d\n", sizeof(&p[0]+1));//一个地址4或者8
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p+1));//5
printf("%d\n", strlen(*p));//这里*p会是一个野指针,段错误
printf("%d\n", strlen(p[0]));//同上
printf("%d\n", strlen(&p));//随机值
printf("%d\n", strlen(&p+1));//随机值
printf("%d\n", strlen(&p[0]+1));//5
cpp 复制代码
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7
printf("%d\n", sizeof(arr+0));//一个地址4或者8
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//一个地址4或者8
printf("%d\n", sizeof(&arr+1));//一个地址4或者8
printf("%d\n", sizeof(&arr[0]+1));//一个地址4或者8
printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr+0));//6
printf("%d\n", strlen(*arr));//野指针,段错误
printf("%d\n", strlen(arr[1]));//野指针,段错误
printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr+1));//随机值
printf("%d\n", strlen(&arr[0]+1));//5
cpp 复制代码
//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//6
printf("%d\n", sizeof(arr+0));//一个地址4或者8
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//一个地址4或者8
printf("%d\n", sizeof(&arr+1));//一个地址4或者8
printf("%d\n", sizeof(&arr[0]+1));//一个地址4或者8
printf("%d\n", strlen(arr));//随机值,无结束标志\0
printf("%d\n", strlen(arr+0));//随机值,无结束标志\0
printf("%d\n", strlen(*arr));//野指针,段错误
printf("%d\n", strlen(arr[1]));//同上
printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr+1));//随机值
printf("%d\n", strlen(&arr[0]+1));//随机值
相关推荐
WL_Aurora1 小时前
Python 算法基础篇之集合
python·算法
坚果派·白晓明1 小时前
【鸿蒙PC三方库移植适配框架解读系列】第一篇:Lycium C/C++ 三方库适配 — 概述与环境配置
c语言·开发语言·c++·harmonyos·开源鸿蒙·三方库·c/c++三方库
平行侠1 小时前
A15 工业路由器IP前缀高速检索与内存压缩系统
网络·tcp/ip·算法
阿旭超级学得完2 小时前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表
li星野2 小时前
位运算 & 数学 & 高频进阶九题通关(Python + C++)
c++·python·学习·算法
jerryinwuhan3 小时前
hello算法,简单讲(1)
算法·排序算法
y = xⁿ3 小时前
20天速通LeetCodeday15:BFS广度优先搜索
算法·宽度优先
400分3 小时前
吃透RAG核心-----语义检索与关键字检索底层原理
算法·架构
目黑live +wacyltd3 小时前
算法备案:常见驳回原因与应对策略
人工智能·算法