目录
前言
1、指针数组
1.1、指针数组的定义
1.2、指针数组详解
2、数组指针
2.1、数组指针的定义
2.2、数组指针详解
3、二维数组与数组指针
4、数组名和数组名取地址的区别
4、数组指针的应用
总结
提示:这里可以添加本文要记录的大概内容:
本文主要介绍指针数组、数组指针、二维数组
指针数组是多个指针变量,以数组的形式存储在内存中,数组中的每个元素都是一个地址,占有多个指针的存储空间。指针数组即存放指针的数组,如:char *array[5];含义是一个存放了5个指向字符型数据的指针的数组。
#includeint main(void)
{
char **p, i;
char *strings[] ={"one", "two", "three"};
p = strings; //strings是地址的地址,所以要定义**p
for(i = 0; i < 3; i++)
printf("%s\n", *(p++)); //这里*(p++)是取出存储在数组中的每一个字符串的地址return 0;
}
//在string[0]存放字符串“one”的首字符的地址,
//string[1]存放字符串“two”的首字符的地址,
//string[3]存放字符串“three”的首字符的地址。
/*****************************************/
void func(char **p) {
char *t;
t = (p += 3)[-1];
printf("%s\n",*p);
printf("%s\n",t);
}
int main() {
int *arr[] = {"ab","ce","ef","gh","ij","kl"};//指针数组
func(arr);
return 0;
}
//输出
//gh
//ef
数组指针是一个指针变量,占有内存中一个指针的存储空间;数组指针即指向数组的指针,如:char (*array)[5];含义是一个指向存放5个字符的数组的指针。
数组指针的定义,如:int (*p)[3]; 首先()的优先级高,所以首先p 和*结合,说明 p是一个指针,然后int 和[3]都是修饰这个指针的,意思是,这个指针指向了一个里面有3个int型元素的数组。
int main() {
int a[3] = {1,2,3};
int (*p)[3] = a;//compile warning: initialization from incompatible pointer type
printf("%p,%p,%p,%p,%d,%d\n",a,&a,p,*p,**p,*p[0]);
return 0;
}
//输出
//0060FEF0,0060FEF0,0060FEF0,0060FEF0,1,1
分析:
p是一个指向数组的指针(这里的p只不过是指针变量的名字,说p指向一个数组,其实就是p变量保存了数组的首地址)那么,在上面的例子中我们把 a 数组的地址给了这个指针变量(注意:&a取得是整个数组的地址)所以p指向了这个数组,p的值是数组首字节的地址。
这里要注意的是*p的类型是int * 类型,为甚么呢?不是 *p应该是这个数组吗?这是因为在C语言中规定,数组“本身”出现在非sizeof,非 & 后面时,会自动转换为指向数组首元素的指针,也就是说,这里的*p转化为数组首元素的指针了(这个指针的值为第一个首元素第一个字节的地址,映射的是四个字节)。
在这个数组中的首元素的类型是int ,所以*p的类型就为int * ,所以 *p的值就和p的值相等了,**p的值就为第一个元素的值 1 ,而*p[0]则因为[]的优先级高,所以 p[0]就是数组首元素的地址,*p[0]就为数组首元素了。
int main() {
int a[5] = { 1, 2, 3, 4, 5 }; //步长为5的数组指针,即数组里有5个元素
int (*p)[5];
p = &a; //把数组a的地址赋给p,则p为数组a的地址,则*p表示数组a本身
printf("%p\n", a); //输出数组a的地址,一般用数组的首元素地址来标识一个数组
printf("%p\n", p); //p为数组a的地址
printf("%p\n", *p); //*p表示数组a本身,一般用数组的首元素地址来标识一个数组
printf("%p\n", &a[0]); //a[0]的地址
printf("%p\n", &a[1]); //a[1]的地址
printf("%p\n", p[0]); //数组首元素的地址
printf("%d\n", **p); //*p表示地址,则*(*p)表示值,当*p表示数组首元素地址时,**p表示首元素本身,即首元素的值1
printf("%d\n", *p[0]); //根据优先级,p[0] 表示首元素地址,则*p[0]表示首元素本身,即首元素的值1
printf("%d\n", *p[1]); //错误,不表示a[1]...表示什么我还不知道
int *p;
p = a;
printf("%c", *p++);
printf("%c", p[1]); //利用数组形式输出printf("%c", *a++); //这里不能改变数组的地址,会报错printf("%c", *(p+1)); //没有改变数组地址,可行
int main() {
int arr[][3] = {1,2,3,4,5,6};
int (*ptr)[3] = arr;
printf("%d,%d\n",(*ptr)[0],(*ptr)[1]);
ptr++; //ptr = ptr + 1;ptr跨过了a[0][],指向了a[1][]
printf("%d,%d\n",(*ptr)[0],(*ptr)[1]);
return 0;
}
//输出
//1,2
//4,5
int main() {
int a[10];
printf("a:/t%p/n", a);
printf("&a:/t%p/n", &a);
printf("a+1:/t%p/n", a+1);
printf("&a+1:/t%p/n", &a+1);
return 0;
}
//输出:
//a: 0012FF20
//&a: 0012FF20
//a+1: 0012FF24
/&a+1: 0012FF48
注意:
(1)、a(a+0)表示&a[0],也即对数组首元素取地址。数组名的值是个指针常量,也就是数组第一个元素的地址。 它的类型取决于数组元素的类型。
(2)、取一个数组名的地址(&a)所产生的是一个指向整个数组的指针,而不是一个指向某个指针常量的指针。所以&a后返回的指针便是指向整个数组的指针,跟a(一个指向a[0]的指针)在指针的类型上是有区别。
(3)、a和&a指向的是同一块地址,但他们+1后的效果不同,a+1是增加一个元素的内存大小(增加4字节)即&a[1],而&a+1增加的是整个数组的内存大小(增加40)。
(4)、当数组名作为sizeof操作符和单目操作符&的操作数时。 sizeof返回整个数组的长度,而不是指向数组的指针的长度。a+1表示首地址+sizeof(元素类型)。&a虽然值为数组首元素地址,但类型为:类型 (*)[数组元素个数],所以&a+1大小为:首地址+sizeof(a)。
若有定义语句:char s[3][10],(*k)[3],*p;,则如下赋值语句正确的是( )
A. p=s;
B. p=k;
C. p=s[0];
D. k=s;
正确答案:C
#define TOUCHKEY_BT_SHORT \
/*00*/ NO_MSG,\
/*01*/ NO_MSG,\
/*02*/ NO_MSG,\
/*03*/ NO_MSG,\
/*04*/ NO_MSG,\
/*05*/ NO_MSG,\
/*06*/ NO_MSG,\
/*07*/ NO_MSG,\
/*08*/ NO_MSG,\
/*09*/ NO_MSG,
#define TOUCHKEY_BT_LONG \
/*00*/ NO_MSG,\
/*01*/ NO_MSG,\
/*02*/ NO_MSG,\
/*03*/ NO_MSG,\
/*04*/ NO_MSG,\
/*05*/ NO_MSG,\
/*06*/ NO_MSG,\
/*07*/ NO_MSG,\
/*08*/ NO_MSG,\
/*09*/ NO_MSG,
#define TOUCHKEY_BT_HOLD \
/*00*/ NO_MSG,\
/*01*/ NO_MSG,\
/*02*/ NO_MSG,\
/*03*/ NO_MSG,\
/*04*/ NO_MSG,\
/*05*/ NO_MSG,\
/*06*/ NO_MSG,\
/*07*/ NO_MSG,\
/*08*/ NO_MSG,\
/*09*/ NO_MSG,
#define TOUCHKEY_BT_LONG_UP \
/*00*/ NO_MSG,\
/*01*/ NO_MSG,\
/*02*/ NO_MSG,\
/*03*/ NO_MSG,\
/*04*/ NO_MSG,\
/*05*/ NO_MSG,\
/*06*/ NO_MSG,\
/*07*/ NO_MSG,\
/*08*/ NO_MSG,\
/*09*/ NO_MSG,
#define KEY_REG_AD_MAX (10)
#define KEY_REG_IO_MAX (10)
#define KEY_REG_IR_MAX (21)
#define KEY_REG_TOUCH_MAX (10)
#define KEY_REG_UART_MAX (10)
const u16 task_bt_touch_table[4][KEY_REG_TOUCH_MAX] = {
/*短按*/ {TOUCHKEY_BT_SHORT},
/*长按*/ {TOUCHKEY_BT_LONG},
/*连按*/ {TOUCHKEY_BT_HOLD},
/*长按抬起*/ {TOUCHKEY_BT_LONG_UP},
};
typedef struct __KEY_REG {
const u16(*_ad)[KEY_REG_AD_MAX];
const u16(*_io)[KEY_REG_IO_MAX];
const u16(*_ir)[KEY_REG_IR_MAX];
const u16(*_touch)[KEY_REG_TOUCH_MAX];
const u16(*_uart)[KEY_REG_UART_MAX];
} KEY_REG;
const KEY_REG task_bt_key = {
._ad = task_bt_ad_table,
._io = task_bt_io_table,
._ir = task_bt_ir_table,
._touch = task_bt_touch_table,
._uart = task_bt_io_table,//task_bt_touch_table,
};
typedef struct __TASK_APP {
// const char *name;
tbool(*skip_check)(void **priv);
void *(*init)(void *priv);
void (*exit)(void **priv);
void (*task)(void *priv);
const KEY_REG *key;
} TASK_APP;
const TASK_APP task_bt_hid_info = {
.skip_check = NULL,
.init = task_bt_hid_init,
.exit = task_bt_exit,
.task = task_bt_deal,
.key = &task_bt_key,
};
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。