目录
19.字符指针变量
*定义
*简单说明
*如果是字符串
*像数组一样指定访问常量字符串的字符
*练习
20.数组指针变量
*定义
*格式
*例子
问题1
问题2
*利用指针打印
21.二维数组传参的本质
*回顾
往期推荐
19.字符指针变量
*定义
指向字符的指针变量,用于存储字符在内存中的地址
cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char a = 'm';
char* pc = &a;
return 0;
}
*简单说明
x86环境下,F11逐语句运行至return 0;
转到内存,输入&a

输入&pc

13 fc 6f 00--倒着写-->00 6f fc 13-->0x006ffc13是a的地址
*如果是字符串
回忆之前的内容
cpp
#include <stdio.h>
int main()
{
char arr[]="abcdef";
char *pc=arr;
return 0;
}
arr数组存储着字符串,arr是数组首元素的地址
类比数组,如果是字符串
cpp
#include <stdio.h>
int main()
{
char* pc = "abcdef";
return 0;
}
x86环境下,F11逐语句运行至return 0;
转到内存,输入&pc

同理倒着写地址
地址框中输入0x00f07bcc 就找到了abcdef

arr数组是一段连续的空间,数组的内容是可以变的,所以常量字符串(char* pc = "abcdef";)(abcdef\0)也是一段连续的空间,常量字符串的内容不可以变(类比const修饰)!
写成下方这样程序会崩溃会报错(写入权限访问冲突):
cpp
char* pc = "abcedf";
*pc = "abc";
*像数组一样指定访问常量字符串的字符
cpp
printf("%c","abcdef"[2]);
访问abcdef常量字符串的第二个字符c
类似于
cpp
char arr[]="abcdef";
printf("%c",arr[2]);
同理
cpp
printf("%s",pc);
类似于
cpp
char arr[]="abcdef";
printf("%s",arr);
*练习
求输出结果
cpp
#include <stdio.h>
int main()
{
char str1[] = "abc";
char str2[] = "abc";
const char* str3 = "abc";
const char* str4 = "abc";
if (str1 == str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if (str3 == str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
分析:上方代码的==不是比较两个字符串的内容是否相等!比较字符串相等用的是strcmp函数
这里比的分别是数组首元素的地址和常量字符串首字符的地址
虽然两个数组的内容一样,但是abc字符串创建了两次,str1和str2存储的数组的首元素的地址不一样,所以not same
由于常量字符串具有内容不可以变的特点,因此abc没有必要创建两次所以str3和str4是same

下面调用内存说明
x86环境下,F11逐语句运行至return 0;
输入&str1
输入&str2

输入&str3

输入&str4

&str3和&str4都是cc 7b fa 00 ,指向地址0x00fa7bcc

20.数组指针变量
*定义
类比字符指针变量的定义,数组指针变量存放的是数组指针(地址)
*格式
数据类型 (*指针变量名称)[数组元素个数]=&数组名
*例子
问题1:以下代码运行是否有错误?
cpp
#include <stdio.h>
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int* p1 = &arr1;
int arr2[5]={ 0 };
int *p2[5] = &arr2;
int arr3[5]={ 0 };
int (*p3)[5] = &arr3;
int arr4[5]={ 0 };
int* (*p4)[5] = &arr4;
return 0;
}
分析:p2的定义出了问题 ,由操作符运算优先级(见15.25【C语言】操作符的属性)可知:*p2[5]代表数组,不能为数组赋值&arr
++[ ]的优先级要高于*号的,所以必须加上()来保证p先和*结合,表明p2是指向数组的指针变量(即数组指针变量),也就是定义p3的写法++
问题2:p1,p3,p4的定义有什么区别
去除int *p2[5]=&arr;这一行后打开调试模式,x86环境下,F11逐语句运行至return 0;
监视arr,p1,p3,p4


打开内存
输入&p1

输入&p3

输入&p4

显然p1是整型指针,p3是数组指针(指向整个含5个int元素的数组的指针),p4是数组指针(指向含5个int*指针的数组的指针)
*利用指针打印
p-->&arr
*p-->*&arr即arr
21.二维数组传参的本质
*回顾
*打印
写法1:实参,形参全是二维数组
cpp
#include <stdio.h>
void test(int a[3][5], int r, int c)
{
int i = 0;
int j = 0;
for(i=0; i<r; i++)
{
for(j=0; j<c; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {{1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7}};
test(arr, 3, 5);
return 0;
}

写法2:指针
回顾:一维数组的数组名是首元素(单个,"0"维数组)的地址,可以推出:二维数组的数组名是首元素(第一行一维数组)的地址,同理三维数组的数组名是首元素(二维数组)的地址
所以可以用指针访问
对上方代码略加改动
cpp
#include <stdio.h>
void test(int (*p)[5], int r, int c)
{
int i = 0;
int j = 0;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d ", p[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };
test(arr, 3, 5);
return 0;
}
打印时p[i][j]有别的写法
如**++*(p+i)[j],*(*(p+i)+j)++**

总结:二维数组传参的本质:传递了地址,传递的是第一行这个一维数组的地址
往期推荐