计算机基础知识——C基础+C指针+char类型

指针

这里讲的很细

https://blog.csdn.net/weixin_43624626/article/details/130715839

内存地址:内存中每个字节单位都有一个编号(一般用十六进制表示)

c 复制代码
存储类型 数据类型 *指针变量名;

int *p; //定义了一个指针变量p,指向的数据是int类型的。

访问指针所指向空间的内容用取内容运算符*

&:取地址符:取变量的地址

*:取内容符:取地址里面存放的内容

*&a=a;//*和&是互逆运算

&*a//错误(因为运算符优先级)

普通变量赋值

c 复制代码
#include <stdlib.h>
int main()
{
    int a = 5;
    int *p = &a;
    char c='v';
    char *q=&c;
    printf("%p %p\n", p, &a);//p为a的地址
    printf("%p %p\n",q,&c);//q为c的地址
    printf("%d %d\n",a,*p);//*p是取地址中的值
    printf("%c %c\n",c,*q);//*q取地址中的值

    printf("Hello, World");
    return(0);
}

注意:指针变量使用前不仅要定义,还要初始化。未初始化的指针变量不能随便使用,不然可能会产生野指针。

通过改变指针指向,改变值

c 复制代码
	int a=10;
    int *p=&a;
    int *q=p;
    printf("%d %d %d\n",a,*p,*q);//10 10 10
    *q=20;//通过指针改变变量a的值
    printf("%d %d %d\n",a,*p,*q);//20 20 20

数组

1.数组的首地址赋值给指针变量

c 复制代码
char s[10]="hello";
char *p = s;
int arr[5]={1,2,3,4,5};
int *q=arr;
printf("%c\n",*p);//h
printf("%d\n",*q);//1

2.指针加减操作其实就是让指针向前向后移动

(1)char 移动1

c 复制代码
	char str[32]="hello";
    char *p=str;
    printf("%c\n",*p);//h
    p++;
    printf("%c\n",*p);//e
    p--;
    printf("%c\n",*p);//h

(2)int 移动4

double 移动 8

偏移了多少字节=n*sizeof(数据类型)

c 复制代码
char str[32]="hello";
    int *p=str;
    printf("%c\n",*p);//h
    p++;
    printf("%c\n",*p);//o
    p--;
    printf("%c\n",*p);//h

运算方法

(1)++和*都是单目运算符

(2)单目运算符从右向左运算

(3)++在前是先移动再取值,++在后是先取值再移动。

c 复制代码
    int x[] = {10, 20, 30};
int *px = x;
printf("%d,", ++*px);//11
printf("%d\n%d", *px,x[0]);//11 

这个++*px把数组里的值给改了

c 复制代码
int x[] = {10, 20, 30};
int *px = x;
printf("%d,", ++*px);//11
printf("%d\n", *px); //11
px = x;
printf("%d,", (*px)++);//11  先取值再+1,所以直接打印x[0]的值,然后再x[0]=11+1=12
printf("%d\n", *px);//12
px = x+1;
printf("%d,", *px++);//20 先取值再移位
printf("%d\n", *px);//30
px = x+1;
printf("%d,", *++px);//30 先移位再取值
printf("%d\n", *px);//30

二维数组

int a[2][3]={1,2,3,4,5,6};

a是数组名,表示第一行的首地址。

a+1表示第二行的首地址,以此类推。

在a前面加*,表示将行地址降级称为列地址。

*a;//第一行第一列的地址

*a+1;//第一行第二列的地址

*(a+1);//第二行第一列的地址

*(a+1)+1;//第二行第二列的地址

原文链接:https://blog.csdn.net/weixin_43624626/article/details/130715839

二级指针

存放指针的地址

c 复制代码
int a = 10;

int *p = &a;

int **q = &p;

数组指针(指向数组)

本质还是指针,指向的是数组 (又称为行指针)

存储类型 数据类型(* 指针变量名)[列数];

例如:

c 复制代码
int a[2][3]={1,2,3,4,5,6};

int (*p)[3]=a;

p可以代替进行元素访问,但本质不同,p是指针变量,a是地址常量。

把p进行运算的时候,例题中情况要3个单位3个单位进行运算。

访问数组元素地址(a[i][j]的地址):

*(p+i)+j

p[i]+j

访问数组元素值:

((p+i)+j)

*(p[i]+j)

c 复制代码
sizeof(p)=4//因为本质还是指针,所以大小都是四字节。

指针数组

指若干个具有相同存储类型和数据类型的指针变量构成的集合。其本质是数组,里面存放的是指针。

存储类型 数据类型 *数组名[元素个数];

指针数组名表示的是该指针数组的首地址。

例如:

int *arr[2];

c 复制代码
int a=10,b=20,c=30;
int *p[3]={&a,&b,&c};

访问b的值:
*p[1]
**(p+1)

访问b的地址:
p[1]
*(p+1)

ASCII

A-65

a-97

相差32

循环队列

循环队列的相关条件和公式:

队尾指针是rear,队头是front,其中QueueSize为循环队列的最大长度

1.队空条件:rearfront
2.队满条件:(rear+1) %QueueSIzefront

3.计算队列长度:(rear-front+QueueSize)%QueueSize

4.入队:(rear+1)%QueueSize

5.出队:(front+1)%QueueSize

char

c 复制代码
char s[]="abcd";
    char ss[]={'a','b','c','d'};
    
    printf("size=%ld\n",sizeof(s));//5
    printf("size=%ld\n",sizeof(ss));//4
    printf("size=%ld\n",strlen(s));//4
    printf("size=%ld\n",strlen(ss));//8

'abcd'='a','b','c','d','\0' 在C语言中,字符串以'\0'作为结束符

所以s长度比s多1

strlen()遇到'\0'停止计数,而数组y中没有'\0',所以strlen()一直向后查找,直至查找到某个'\0'为止。
strlen统计字符串长度,遇到\0结束,且不统计\0sizeof计算开辟的空间大小

字符串

把字符串储存在char类型的数组中,如果char类型的数组末尾包含一个表示字符串末尾的空字符\0,则该数组中的内容就构成了一个字符串。

因为字符串需要用\0结尾,所以在定义字符串的时候,字符数组的长度要预留多一个字节用来存放\0,\0就是数字0。这是约定。

字符串采用双引号包含起来,如:"hello"、"你好"、"A"、"",这是约定。

例题

1.内存占用大小和初始化

个字符占用一字节的内存,字符串定义时数组的大小就是字符串占用内存的大小。

c 复制代码
memset(strname,0,sizeof(strname));  // 把全部的元素置为0

2.在C语言中,数组名是数组元素的首地址,字符串是字符数组,所以在获取字符串的地址的时候,不需要用&取地址

c 复制代码
char strname[21];
memset(strname,0,sizeof(strname));
scanf("%s",strname);//acc
printf("%s\n",strname); //acc
printf("%c",strname[1]);//c

字符串的结尾标志是0

c 复制代码
    char strname[21];
memset(strname,0,sizeof(strname));
scanf("%s",strname);//ac0cc
printf("%s\n",strname);  //ac0cc
strname[3]=0;//或strname[3]='\0';// 强制把第4个元素赋值0
printf("%s\n",strname); //ac0
printf("%c",strname[1]);//c

把赋值为0或'/0'后面的不要,变成内存中的垃圾值

4.字符串是字符数组 ,字符串越界就是数组越界。

char i = 1;则i的ASCII就是1,在内存中就是0 0 0 0 0 0 0 1

char i = '1';则i的ASCII就是字符'1'的ASCII码49,就是0 0 1 1 0 0 0 1

将一个字符常量放到一个字符变量中,实际上并不是把该字符本身放到内存单元中去,而是把该字符的相应ASCII代码放到存储单元中。

【A选择:】数组越界。所以错误。

【B选择:】声明char类型,传入了数值数组,而数值会以char类型的ASCII编码写入。所以正确。

【C选择:】 数组声没明显不符合规范,左侧声明名后应加上[]。所以错误。

【D选择】:这种声名只能用字符型char等。所以错误。

对于D选项:

c 复制代码
 int a[5]={'1'};//49,0,0,0,0 这样行,但D中等号右侧没有{}
 int a[5]={1};//1,0,0,0,0

'e' 的ASCII是101,而字符s第一个是'a '。也就是说只写这么个s就代表它的第一个值是s[0]

'e' - 'a'为两个字符之间的ASCII差值=4

gets和scanf输入都是需要取地址,数组名a等价于首元素地址&a[0],a+1相当于&a[1]。所以D选项没有取地址才错。

参数类型为 char* 型,即 str ,它可以表示这个数组的首地址,所以B 正确

BC选项:

int *s[8]; //定义一个指针数组,该数组中每个元素是一个指针,每个指针指向哪里就需要程序中后续再定义了。

int (*s)[8]; //定义一个数组指针,该指针指向含8个元素的一维数组,每个都指向对应的数组的每列 。

主要在于看运算符优先级:int *p[n]; 中,运算符[ ]优先级高;int (*p)[n]; 中( )优先级高。

数组作为实参时必须指定列数

否则可能产生歧义,所以D正确 。

相关推荐
爱上电路设计4 小时前
有趣的算法
开发语言·c++·算法
studyForMokey4 小时前
kotlin 函数类型接口lambda写法
android·开发语言·kotlin
2401_858120264 小时前
探索sklearn文本向量化:从词袋到深度学习的转变
开发语言·python·机器学习
与墨学长5 小时前
Rust破界:前端革新与Vite重构的深度透视(中)
开发语言·前端·rust·前端框架·wasm
虫小宝5 小时前
Java中的软件架构重构与升级策略
java·开发语言·重构
CTGU_daffodil6 小时前
matlab 绘制高等数学中的二维函数示例
开发语言·matlab
立秋67896 小时前
使用Python绘制堆积柱形图
开发语言·python
逸群不凡6 小时前
C++|哈希应用->布隆过滤器
开发语言·数据结构·c++·算法·哈希算法
敲代码的小白帆6 小时前
跟着峰哥学java 第四天 商品分类 前后端显示
java·开发语言
friklogff6 小时前
【JavaScript脚本宇宙】美化网格布局:Isotope和Masonry让你的网页焕然一新
开发语言·前端·javascript