一.地址
概念:每一块内存单元(大小固定 1byte)的编号
取地址:&(取地址符)+变量名
打印地址: 使用%p
通过解引用操作符,可以获取地址中存放的值:*&变量名===>*地址常量===>地址存放的值
保存地址: 【数据类型(指针类型——>与变量名有关) 变量名(指针变量——>简称指针) = 取地址表达式】
eg:float* p=&scores
指针类型所占空间大小:
- 64位系统占8个byte
- 32位系统占4个byte
- 16位系统占2个byte
去掉变量名剩下的就是类型
eg: float*** float** float*
指针实例:
eg:float score = 25.6
- 一级指针float*p = &score
- *p==*&score==score==25.6
- 二级指针float**pp = &p;
- *pp==*&p==p==&score
- **pp==**&p==*p==*&score==25.6
- 三级指针float***ppp = &pp
- *ppp==*&pp==pp==&p
- **ppp==**&pp==*&p==p==&score
- ***ppp==***&pp==**pp==**&p==*p==*&score==25.
*和&相互抵消 指针变量是用来保存地址
二.数组与指针
一维数组与指针:
- arr----数组名-----表示数组首元素的地址
- &arr[0]----数组首元素的地址
- arr[0]----数组首元素的值
- eg: arr[i](本身代表arr中第i-1个元素的值)——>*(&arr[i])——>*(arr+i) (arr本身指向&arr[0])
指针偏移:
- &arr+1偏移整个数组 &arr表示的是整个数组的地址+1后自动偏移一整个数组
- arr+1偏移到一维数组中的第二个元素
特例:sizeof(arr),&arr表示的是整个数组
二维数组与指针:
- scores[2][3] 直接使用数组的方式进行获取
- *(scores[1]+2) 指向第二行首元素再偏移到第三列
- *(&scores[1][0]+2) &scores[1][0]==scores[1]
- *(*(scores+1)+2) scores指向&scores[0]+1==&scores[1]解完引用后是scores[1]
- *(*(&scores[1])+2) 取到scores的地址后再解引用掉就相当于scores[1]
- *(*(&scores[0]+1)+2) &scores[0]+1在行上偏移1个取到*(scores[1])
scores指向&scores[0] score[0]指向&score[0][0]
&score[0][0]+1在列上偏移1个取到*(scores[0][1])
数组名及数组首元素地址arr指向arr[0]二维也就是arr[0][0]
指针数组与数组指针:
数组指针:数组的指针,这个指针有什么功能?指向数组的指针
eg:int (*arr)[6] 它分配的空间大小是8个字节的指针空间
指针数组: 指针的数组,这个数组有什么功能?保存指针的数组
eg:int*arr[6] 它分配的空间大小是24个字节的数组空间
为什么会有不同类型的指针?
不同类型的指针决定了指针一步走多远
如下,对pc和pa进行变动时,地址偏移大小不同
大小端模式
小端模式:高地址放大值,低地址存放小值
大端模式:高地址放小值,低地址存放大值
三.指针和数组的应用:
题目:一副扑克有54张牌,打牌时应将牌分给三个人,每人17张,底牌留3张,请设计一个程序完成自动发牌的工作。要求黑桃用S表示,红桃用H表示,方块用D表示,梅花用C表示。
1>使用一维数组表示四种花色和大小王char colors[4]={'S','H','D','C','K','X'}; // K表示大王 X表示小王
2>使用一维数组表示每种花色的13张牌char cards[13]={'A','2','3','4','5','6','7','8','9','T','J','Q','K'};
3>使用随机函数发牌时,先随机花色,再随机号码。如果随机到大王或小王,就不用随机号码。花色与号码组成一张牌。如果随机出的牌已经发给用户,就重新随机生成,知道随机出一个未出现的牌
4>每个用户的牌使用二维数组表示char user1[17][10]={0};char user2[17][10]={0};char user3[17][10]={0};
5>底牌也使用二维数组表示char othercards[3][10]={0}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define COLOR_CARDS 6
#define NUMBER_CARDS 17
int main()
{
char colors[6] = { 'S','H','D','C','K','X' };
char numbers[13] = { 'A','2','3','4', '5' ,'6', '7', '8', '9','丅','J', 'Q','K' };
char user1[6][13] = { 0 };
char user2[6][13] = { 0 };
char user3[6][13] = { 0 };
char sy[6][13] = { 0 };
//char numbers[13] = { 'A','2','3','4', '5' ,'6', '7', '8', '9','丅','J', 'Q','K' };
char cards[54][10] = { 0 };
int count = 0;
srand((unsigned int)time(NULL));
while (count < 54)
{
char card[3] = { 0 };
int colorindex = rand() % 6;
card[0] = colors[colorindex];
int numberlndex = -1;
if (*(colors + colorindex) != 'K' && *(colors + colorindex) != 'X')
{
// 如果生成的不是大小干,就随机生成号码 / 1.3 随机生成号码
numberlndex = rand() % 13;
card[1] = numbers[numberlndex];
}
else {
card[1] = '*';
}
// 判断是否重复
// 使用strcmp函数判断是否重复
int isRepeat = 0;
for (int i = 0; i < count; i++)
{
// 重复
if (strcmp(card, cards[i]) == 0)
{
isRepeat = 1;
break;
}
}
if (!isRepeat)
{
//使用strcpy函数将生成的牌放入cards
// 不重复,就需要给用户分发牌,并蒋生成的牌放入cards中if(lisRepeat)
strcpy(cards[count], card);
// 分发牌的代码
if (count < 17)
{
if (numberlndex == -1) {
user1[colorindex][0] = '*';
}
else {
user1[colorindex][numberlndex] = numbers[numberlndex];
}
}
count++;
}
}
//用于打印
printf("用户1:\n");
int a = 0;
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 13; j++) {
if (user1[i][j] != 0) {
a++;
switch (i)
{
case 0:
printf("黑桃:");
break;
case 1:
printf("红桃:");
break;
case 2:
printf("方块:");
break;
case 3:
printf("梅花");
break;
case 4:
printf("大王");
break;
case 5:
printf("小王");
break;
}
printf("%c\n", user1[i][j]);
}
}
}
printf("a=%d\n",a);
return 0;
}