指针进阶(C语言)

news2024/11/23 17:58:06

目录

字符指针

使用方法:

1、指向字符

2、指向字符串的首地址

指针数组

数组指针

数组指针的定义

数组名表示的含义

数组指针的使用

数组参数、指针参数

一位数组传参

二维数组传参

一级指针传参

二级指针传参

函数指针

函数指针数组

指向函数指针数组的指针

回调函数

1、如何使用qsort:

2、模拟实现qsort:

指针和数组笔试题解析

指针变量笔试题

第一题:

第二题:

第三题:

第四题:

第五题:

第六题:

第七题:

第八题:


由初阶指针可知:

1、指针就是地址

2、指针变量是存放指针(地址)的变量

3、我们在口语上把指针变量也叫指针

      所以要严格区分指针和指针变量

4、指针的大小是固定的32位:4 / 64位:8个字节

5、指针变量的类型:

      指针的类型加减整数的步长

      解引用操作访问空间的权限

6、指针的运算

      指针-指针,可计算出两个指针之间的元素个数

      指针与指针可比较大小

这篇文章带你更深入的了解指针

字符指针

顾名思义字符指针就是指向字符的指针

我们知道指针是有类型的

而字符指针的类型:char*

字符指针的两种使用方法:

1、指向字符

2、指向字符串的首元素地址

使用方法:

1、指向字符

就是字符指针变量里面存的是一个字符的地址

可通过解引用操作来访问这个字符

#include <stdio.h>

int main()
{
	char c = 'a';
	char* p = &c;

	//通过指针解引用取到字符
	printf("%c\n", *p);

	//通过指针修改字符
	*p = 'b';
	printf("%c\n", c);

	return 0;
}

2、指向字符串的首地址

字符指针变量指向字符串的首地址

字符指针变量里面存放的是字符串的首元素地址

可通过字符指针访问整个字符串

用%s打印整个字符串:

    %s打印的时候从起始位置开始直到遇到'\0'结束

#include <stdio.h>
int main()
{
	const char str[] = "hello";

	//数组名表示首元素的地址
	//p里面存放的是字符串首元素的地址
	//也就是字符'h'的地址
	char* p = str;
	//通过指针p访问整个字符串
	printf("%s\n", p);

	return 0;
}

一道典型笔试题:

#include <stdio.h>
int main()
{
	char str1[] = "hello world";
	char str2[] = "hello world";
	const char* p = "hello world";
	const char* q = "hello world";

	//str1 和 str2 是不同的两块空间
	//数组名表示首元素地址
	//所以str1的首元素地址,跟str2的首元素地址不相同
	if (str1 == str2)
	{
		printf("st1 等于 str2\n");
	}
	else
	{
		printf("str1 不等于 str2\n");
	}

	//因为hell world 是常量字符串,存放在内存常量区
	//指针 p 和 q 都指向这个常量字符串的首地址
	// 所以p 和 q相同
	if (p == q)
	{
		printf("p 等于 q\n");
	}
	else
	{
		printf("p 不等于 q\n");
	}

	return 0;
}

指针数组

指针数组本质上是一个数组

而数组里面存放的是指针

int* p[5];  --> 指针数组

因为[]的优先级高于* 

所以p先和[]结合,是一个数组

该数组里面有5个元素,每个元素是int*类型的

#include <stdio.h>
int main()
{
	//整型指针数组
	int* arr[10];
	
	//浮点型指针数组
	float* frr[10];

	//字符型指针数组
	 char* str1[10];
	//我们知道用一个字符指针可以指向一个字符串的首地址
	//然后可通过这个指针访问整个字符串
	//我们可以给字符指针数组这样赋值
	char* str[] = { "abcd","efgh","lmno","pqrstuv" };
	int sz = sizeof(str) / sizeof(str[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s\n", str[i]);
	}

	return 0;
}

数组指针

数组指针本质上一个指针

而这个指针指向的是数组

指针里面存放的是数组的地址

数组指针的定义

我们知道指针表示:

整型指针:int* p; 能够指向整型的指针

字符型指针:char* p; 能够指向字符型的指针

浮点型指针:float* p; 能够指向字符型的指针

那么数组指针的类型我们该怎么写呢?

int(*p)[5]; -- >数组指针  (整型数组指针)

[]的优先级要高于*号的,所以必须加上()来保证p先和*结合

*号先和p结合说明是一个指针,除去*和p就是指针所指向的类型

该指针指向的数组总共有五个元素,且每个元素都是int*类型的

#include <stdio.h>
int main()
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };

	//定义一个整型数组指针,并将这个整型数组的地址赋给指针
	int(*p)[10]=&arr;

	char str[10] = "abcdef";

	//定义一个字符数组指针,并将这个字符数组的地址赋值给q;
	char(*q)[10] = &str;

	float frr[5] = { 1.2,1.3,1.5,1.6,0.8 };

	//定义一个浮点型数组指针,并将浮点型数组的地址赋值给指针
	float(*f)[5] = &frr;

	//去掉*和指针变量名,就是指针所指向的类型

	return 0;
}

数组名表示的含义

数组名单独出现的情况:

数组名只有在两种情况下表示整个数组

sizeof(数组名) 和   &数组名 表示整个数组

其它情况下数组名都表示首元素的地址

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };

	//数组名
	printf("%p\n", arr);//表示首元素地址
	printf("%p\n", &arr);//表示整个整租的地址

	//地址+1的步长就能看出地址是数组的地址还是首元素地址
	printf("%p\n", arr + 1);
	printf("%p\n", &arr + 1);

	return 0;
}

数组指针的使用

数组指针是指向数组的指针

那具体改怎么使用呢?

看以下代码:

#include <stdio.h>
void print(int(*arr)[5], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			//printf("%d ", arr[i][j]);
			printf("%d ", *(*(arr + i) + j));// *(arr+i) 得到每一行首元素的地址
		}
		printf("\n");
	}
}

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int(*p)[10] = &arr;//数组指针

	int a[2][5] = { {1,2,3,4,5},{6,7,8,9,10} };

	//数组名表示首元素的地址,二维数组首元素是一个一维数组
	//也就是二维数组第一行(一位数组)的地址
	print(a, 2, 5);
	//传过去的是一个一位数组的地址,用一个数组指针来接收
	return 0;
}

int arr[5];  ---->  整型数组
int *parr1[10]; ------> 指针数组
int (*parr2)[10];------> 数组指针
int (*parr3[10])[5]; -------> 数组指针数组

数组参数、指针参数

当我们把数组或者指针传给函数时

函数的参数改如何设计呢?

下面我们仔细了解一下函数参数的设计

一位数组传参

一位数组在传参的时候

传过去的是数组名

也就是数组首元素的地址

因为传的是首元素的地址

我们在接收的时候用指针接收

在书写的时候可以写成指针的形式

也可以写成数组的形式

#include <stdio.h>
//以指针的形式接收
void print_arr(int* arr, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
//以数组的形式接收
void print2_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

int main()
{
	int arr[] = {1,2,3,4,5};
	int sz = sizeof(arr) / sizeof(arr[0]);
	
	//指针形式接收
	print_arr(arr, sz);
	printf("\n");

	//数组形式接收
	print2_arr(arr, sz);
	return 0;
}

二维数组传参

二维数组传参的时候

传的是数组名

数组名表示首元素地址

二维数组的首元素表示第一行(一维数组)

所以数字名表示的是一维数组的地址

在传参的时候传过去的是第一行一维数组的地址

在接收的时候用数组指针接收

也可用二维数组的形式接收,但二维数组的列不可以省略!

#include <stdio.h>
//用数组指针接收
void print_arr(int(*arr)[5], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
		//	printf("%d ", arr[i][j]);
			printf("%d ", *(*(arr + i) + j));//arr[0] 起始就是第一行一维数组的数组名
		}
		printf("\n");
	}
}

//用二维数组形式接收,二维数组的行不可省略
void print2_arr(int arr[][5], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

int main()
{

	int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15} };

	print_arr(arr, 3, 5);

	return 0;
}

一级指针传参

指针传参就用指针接收

当函数参数是一个一级指针时我们能传什么过去?

1、可以传一级指针变量

2、可传变量的地址

3、可传一维数组

#include <stdio.h>
void print(int *p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9 };
	int *p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);

	//一级指针p,传给函数
	print(p, sz);
	return 0;
}

二级指针传参

二级指针传参用二级指针接收

当函数参数是一个二级指针时我们能传什么过去?

1、可以传二级指针变量

2、可以传一级指针变量的地址

3、可以传指针数组

#include <stdio.h>
void print(char** p,int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s\n", p[i]);
	}
}

int main()
{
	int a = 10;
	int* p = &a;
	int** q = &p;

	char* str[] = { "abcd","efg","hij" };
	int sz = sizeof(str) / sizeof(str[0]);
	print(str, sz);

	return 0;
}

函数指针

我们所知的函数也是有地址

为什么函数也有地址呢?

因为函数有自己的函数栈帧

函数栈帧是占用内存空间的

而内存中每个字节都有自己特定的编号(也就是地址)

由此我们可推断出函数也有地址

那如何取到函数的地址呢?

        1、&函数名 可以取到函数的地址

        2、函数名 表示函数的地址

如何存放函数的地址?

  打个比方:

     整型指针整型变量的地址

     浮点型指针存放浮点型变量的地址

     字符型指针存放字符型变量的地址

........

由此可知:

        用函数指针来存放函数的地址

函数指针的类型该怎么写呢?

函数的返回类型,函数的参数都要写在类型中

返回类型 *指针变量名 ( 参数类型 )

假设函数:

返回类型为 int, 参数为int

则它的指针类型为:int (*p) ( int ,int );

p先和*号结合说明是一个指针

而指针指向的类型为返回值为int,参数为:int,int的函数类型

返回类型为:float, 函数参数为两个(int ,double)

则它的指针类型为:float(*p) ( int , double )

..........

两个出自《C指针与缺陷》的典型代码:

1、(*(void (*)( ) ) 0 ) ();

将数字0先强制类型转化成函数指针(void(*)())类型

再以指针的方式调用0地址处的函数(会报错)

2、void (*signal(int , void(*)(int)))(int);

signal与()先结合,说明是一个函数

函数的参数有两个分别是:int 和 void(*)(int)

函数的返回类型是:void(*)(int);

参数是(一个整型)和(一个指向返回值为void 参数为int 的函数指针)

返回值是:一个指向返回值为void 参数为int 的函数指针

#include <stdio.h>

void test(int x)
{
	printf("%d\n", x);
}

int main()
{
	int n = 19;
	test(n);

	//取到函数的地址
//  1、&test;
//  2、test;
	
	//将函数的地址用函数指针变量存储起来
	void (*p) (int) = test;
	void (*q) (int) = &test;

	//通过函数指针调用函数
	int a = 10;
	//第一种调用函数
	p(a);
	//第二种调用函数
	int b = 20;
	(*q)(b);

	//其实调用的时候函数指针变量前面的*号可以省略
	int c = 40;
	q(c);
	//其实这个*号也可当成是一种摆设,不管加几个都可以调用
	int d = 50;
	(********q)(d);//加多少个*号都可以调用!

	return 0;
}

函数指针数组

我们知道数组是相同元素的集合

也就是相同类型的空间

数组里面的元素,可以是整型、浮点型、字符型

也可以是指针类型:

int* arr[10]; --> 整型指针数组

数组里面存放10个元素,每个元素的类型是int*

而存放函数地址的数组被称为,函数指针数组

函数指针数组的定义:

int (*ptr[5]) (int,int);  -->函数指针数组

ptr先和[]结合是一个数组,数组里面有五个元素

每个元素的类型是:int(*) (int,int)

(也就是指向返回值为int 两个参数都为int的函数指针)

函数指针的用途:转移表

看以下代码:

#include <stdio.h>

//例子:计算器

//按正常繁琐思路实现

void mnue(void)
{
	printf("*************************\n");
	printf("**** 1:add  2:sub ******\n");
	printf("**** 3:mul  4:dvi ******\n");
	printf("****** 0:exit **********\n");
	printf("*************************\n");

}

int add(int x, int y)
{
	return x + y;
}

int sub(int x, int y)
{
	return x - y;
}

int mul(int x, int y)
{
	return x * y;
}

int dvi(int x, int y)
{
	return x / y;
}

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	do {
		mnue();//菜单
		printf("请选择--> ");
		scanf("%d", &input);
		int ret = 0;
		switch (input)
		{
		case 1:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret = add(x,y);
			printf("%d + %d = %d\n",x,y, ret);
			break;
		case 2:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			 ret = sub(x, y);
			printf("%d - %d = %d\n", x, y, ret);
			break;
		case 3:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
		    ret = mul(x, y);
			printf("%d * %d = %d\n", x, y, ret);
			break;
		case 4:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret = dvi(x, y);
			printf("%d / %d = %d\n", x, y, ret);
			break;
		case 0:
			printf("退出成功\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

	return 0;
}






//按照函数指针数组实现

void menu(void)
{
	printf("*************************\n");
	printf("**** 1:add  2:sub ******\n");
	printf("**** 3:mul  4:dvi ******\n");
	printf("****** 0:exit **********\n");
	printf("*************************\n");
}

int add(int x, int y)
{
	return x + y;
}

int sub(int x, int y)
{
	return x - y;
}

int mul(int x, int y)
{
	return x * y;
}

int dvi(int x, int y)
{
	return x / y;
}

//创建一个函数指针数组
//转移表
int (*p[5])(int, int) = { NULL,add,sub,mul,dvi };
int main()
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int input = 0;
	do {
		menu();
		printf("请选择:");
		scanf("%d", &input);
		if (input >= 1 && input <= 4)
		{
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = p[input](x, y);
			printf("%d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出成功\n");
		}
		else
		{
			printf("输入有误,请重新输入\n");
		}
	} while (input);

	return 0;
}

指向函数指针数组的指针

那么什么是指向函数指针数组的指针呢?

我们慢慢分析这句话

它是一个数组指针

而这个指针指向一个数组

数组里面的元素类型是函数指针

也就是一个指向数组的数组指针而数组里面存放的是函数指针

指向函数指针数组的指针是一个 指针
指针指向一个 数组 ,数组的元素都是 函数指针

#include <stdio.h>

void test(const char* str)
{
	printf("%s\n", str);
}

int main()
{
	char* str = "hello";

	//函数指针
	void(*p) (const char*) = test;

	//函数指针数组
	void(*q[5])(const char*);
	q[0] = test;

	//指向函数指针数据的指针
	void (*(*ptr)[5]) (const char*);
	//ptr先与*结合 是一个指针,再与括号结合 是一个指向数组的数组指针
// ptr指向一个数组 数组里面有五个元素,每个元素的类型是一个返回值为空,参数为char*的函数指针

	return 0;
}

回调函数

回调函数就是一个通过函数指针调用的函数。

如果你把函数的指针(地址)作为参数传递给另一个函数,

当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

回调函数不是由该函数的实现方直接调用,

而是在特定的事件或条件发生时由另外的一方调用的,

用于对该事件或条件进行响应。

回调函数例子:qsort函数

如下代码:

1、如何使用qsort:

#include <stdio.h>

//qsort函数的使用

//qsort函数的原型:
//void qsort(void* base,
//		    size_t num,
//		    size_t size,
//	        int(*compar)(const void*, const void*));
//第一个参数是要排序的数组
//第二个参数是数组的元素个数
//第三个参数是数组的单个元素的大小
//第四个元素是一个函数指针,返回值为int 两个参数为const void* 的函数,这个函数是自己实现的

//定义结构体
struct ss {
	char name[10];
	int age;
};

//排序整型
int com_int(const void* e1, const void* e2)
{
	//升序:从小到大排序
	//return *((int*)e1) - *((int*)e2);

	//降序:从大到小排序
	return *((int*)e2) - *((int*)e1);
}

//排序字符
int com_char(const void* e1, const void* e2)
{
	//升序,从小到大排序
	return *((char*)e1) - *((char*)e2);

	//降序,从大到小排序
	//return *((char*)e2) - *((char*)e1);
}

//按照age排序结构体
int com_age(const void* e1, const void* e2)
{
	//升序排序
	//return ((struct ss*)e1)->age - ((struct ss*)e2)->age;

	//降序排序
	return ((struct ss*)e2)->age - ((struct ss*)e1)->age;
}

//按照name排序
int com_name(const void* e1, const void* e2)
{
	//升序排序
	return strcmp(((struct ss*)e1)->name , ((struct ss*)e2)->name);

	//降序排序
	//((struct ss*)e2)->name - ((struct ss*)e1)->name;
}
int main()
{
	//qsort排序整型
	int arr[] = { 3,5,4,1,2 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), com_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

	//qsort排序字符
	char str[] = "bdfeca";
	sz = strlen(str);
	qsort(str, sz, sizeof(str[0]), com_char);
	printf("%s\n", str);


	//qsort 排序结构体
	struct ss aa[3] = { {"zhangsan",25},{"wangwu",36},{"lisi",20} };//定义结构体变量
	sz = sizeof(aa) / sizeof(aa[0]);
	//用年龄排序
	qsort(aa, sz, sizeof(aa[0]), com_age);
	for (i = 0; i < sz; i++)
	{
		printf("%s  %d\n", aa[i].name, aa[i].age);
	}
	printf("\n");
	//用名字排序
	qsort(aa, sz, sizeof(aa[0]), com_name);
	for (i = 0; i < sz; i++)
	{
		printf("%s   %d\n", aa[i].name, aa[i].age);
	}
	return 0;
}

2、模拟实现qsort:

#include <stdio.h>

//用冒泡排序算法 模拟实现qsort函数

qsort函数的原型:
void qsort(void* base,
		    size_t num,
		    size_t size,
	        int(*compar)(const void*, const void*));

int com_int(const void* e1, const void* e2)
{
	//升序 从小到大
	//return *((int*)e1) - *((int*)e2);

	//降序 从大到小
	return *((int*)e2) - *((int*)e1);
}

int com_char(const void* e1, const void* e2)
{
	//升序 从小到大
	return *((char*)e1) - *((char*)e2);

	//降序 从大到小
	//return *((char*)e2) - *((char*)e1);
}

void swap(void* p1, void* p2, int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *((char*)p1+i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}

void my_qsort(void* be, size_t sz, size_t size, int(*p)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (p((char*)be + j * size, (char*)be + (j + 1)*size) > 0)
			{
				//交换
				swap((char*)be + j * size, (char*)be + (j + 1)*size, size);
			}
		}
	}
}

int main()
{
	//排序整数
	int arr[] = { 3,5,1,4,2 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, sz, sizeof(arr[0]), com_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	//排序字符型
	char str[] = "dabefc";
	sz = strlen(str);
	qsort(str, sz, sizeof(str[0]), com_char);
	printf("%s\n", str);

	return 0;
}

指针和数组笔试题解析

下面有几道笔试题供大家观看

我们以代码的方式,注释讲解

代码如下:

#include <stdio.h>

//第一题

int main()
{
	//一维数组
	//sizeof()操作符用来数据计算占用内存空间的大小单位是字节
	//sizeof() 括号中的表达式是不参与运算的
	//地址(指针)的大小在32位平台下是4字节,在64位平台下是8字节
	int a[] = { 1,2,3,4 };

	printf("%d\n", sizeof(a));//sizeof(数组名)数组名单独出现,代表整个数组,计算整个数组的大小,大小为:16

	printf("%d\n", sizeof(a + 0));//数组名a表示首元素地址,让地址+0 等同于没加 还是地址,地址的大小为 :4/8

	printf("%d\n", sizeof(*a));//数组名a表示首元素地址,指向首元素,给指针解引用取到的是首元素的内容 1,数字1是整型大小为4个字节

	printf("%d\n", sizeof(a + 1));//数组名表示首元素的地址 让首地址+1 取到第二个元素的地址,还是地址,地址的大小为:4/8 字节

	printf("%d\n", sizeof(a[1]));// a[1] 等同于 *(a+1),表示第二个元素 数字2,数字2是int类型,int的大小为4字节

	printf("%d\n", sizeof(&a));// &a 取到的是整个数组的地址,但本质还是地址,地址的大小为:4/8 字节

	printf("%d\n", sizeof(*&a));//*&a 给整个数组的地址进行解引用取到的是整个数组的内容,*&a 等同于 a 表示整个数组,大小为:16

	printf("%d\n", sizeof(&a + 1));//&a取到数组的地址,让数组的地址+1 还是地址,地址的大小为:4/8 字节

	printf("%d\n", sizeof(&a[0]));//&a[0] 取到的是首元素的地址 等同于 &*(a+0) 还是地址 地址的大小为:4/8字节

	printf("%d\n", sizeof(&a[0] + 1));// &a[0]取到首元素的地址,首元素地址+1 还是地址 地址的大小为:4/8字节

	return 0;
}



// 第二题

int main()
{
	//字符数组
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));//6 sizeof(数组名) 单独出现表示整个数组 大小为:6 字节

	printf("%d\n", sizeof(arr + 0));// 4/8 arr表示首元素地址,aar+0 还是首元素地址,地址大小为:4/8 字节

	printf("%d\n", sizeof(*arr));// 数组名表示首元素地址 对数组名进行解引用,取到首元素内容,大小为:1字节

	printf("%d\n", sizeof(arr[1]));// arr[1] 等同于 *(arr+1) 取到首元素内容  大小为:1字节

	printf("%d\n", sizeof(&arr));//&arr 表示整个数组的地址,还是地址,大小为:4/8 字节

	printf("%d\n", sizeof(&arr + 1));// &arr 表示整个数组的地址,&arr+1 跳过整个数组指向下一片空间,还是地址 大小为:4/8 字节

	printf("%d\n", sizeof(&arr[0] + 1));// &arr[0] 取到首元素地址,让首元素地址+1 是第二个元素的地址,本质还是地址,大小为:4/8 字节

	
	// strlen 函数计算字符串的长度,遇到'\0'停止
	// strlen 只计算’\0'之前的个数
	// strlen 的参数是一个指针,也就是要传一个地址进去
	// 从传进去的地址开始往后计算 碰到 \0 结束

	printf("%d\n", strlen(arr));// 随机值 因为arr字符数组里面没有'\0' 所以不知道会到那个位置停止

	printf("%d\n", strlen(arr + 0));// arr表示首元素地址,arr+0还是首元素地址,结果还是随机值

	printf("%d\n", strlen(*arr));// err 报错,因为传进去的是 一个字符‘a' ASICC值为97,将97解读成地址传过去,非法的

	printf("%d\n", strlen(arr[1]));// err 报错,传进去的还是第一个元素,97 非法

	printf("%d\n", strlen(&arr));// 随机值,&arr表示整个数组的地址,但整个数组的地址还是取到数组最低位的地址,最低位的地址就是首元素的地址,从首元素的位置开始计算

	printf("%d\n", strlen(&arr + 1));//随机值 &arr表示整个数组的地址,&arr+1 取到数组后面空间的地址,从后面空间开始计算

	printf("%d\n", strlen(&arr[0] + 1));//随机值 &arr[0] 取到首元素地址 &arr[0]+1 取到第二个元素的地址,从第二个元素地址开始计算

	return 0;
}




//第三题

int main()
{
	//	//sizeof()操作符用来数据计算占用内存空间的大小单位是字节
//	//sizeof() 括号中的表达式是不参与运算的
//	//地址(指针)的大小在32位平台下是4字节,在64位平台下是8字节

	char arr[] = "abcdef";

	printf("%d\n", sizeof(arr));//sizeof(数组名)表示整个数组,整个数组的大小为:7

	printf("%d\n", sizeof(arr + 0));// arr表示首元素地址 arr+0还是首元素地址 本质是地址 大小为:4/8 字节

	printf("%d\n", sizeof(*arr));// arr表示首元素地址,*arr 取到首元素内容 ’a‘ 大小为:1 字节

	printf("%d\n", sizeof(arr[1]));// arr[1] 取到首元素内容 ’a' 大小为:1 字节

	printf("%d\n", sizeof(&arr));// &arr 表示整个数组的地址,本质上是地址 大小为:4/8 字节

	printf("%d\n", sizeof(&arr + 1));// &arr 表示整个数组的地址,&arr+1 指向数组后面的一片空间,还是地址,大小:4/8 字节

	printf("%d\n", sizeof(&arr[0] + 1));// &arr[0] 取到的是首元素的地址 &arr[0]+1 指向第二个元素,还是地址,大小:4/8 字节


	//	// strlen 函数计算字符串的长度,遇到'\0'停止
//	// strlen 只计算’\0'之前的个数
//	// strlen 的参数是一个指针,也就是要传一个地址进去
//	// 从传进去的地址开始往后计算 碰到 \0 结束

	printf("%d\n", strlen(arr));// arr表示首元素地址,从首地址开始往后数 遇到\0 结束 6

	printf("%d\n", strlen(arr + 0));//arr表示首元素地址,arr+0还是首元素地址,6

	printf("%d\n", strlen(*arr));// arr表示首元素地址 *arr是首元素内容,‘a' 97 非法 err报错
	
	printf("%d\n", strlen(arr[1]));//arr[1]表示首元素内容 ’a' 97解读成地址传过去  非法 err报错

	printf("%d\n", strlen(&arr));//&arr表示整个数组的地址,但整个数组的地址还是取到数组最低位的地址,最低位的地址就是首元素的地址,从首元素的位置开始计算 6

	printf("%d\n", strlen(&arr + 1));// &arr表示整个数组的地址,&arr+1 指向数组后面的一片空间,开始计算,随机值

	printf("%d\n", strlen(&arr[0] + 1));//&arr[0]表示首元素地址,&arr[0]+1 取到第二个元素地址,从第二个元素地址开始计算 5

	return 0;
}



//第四题
int main()
{
	char *p = "abcdef";

	printf("%d\n", sizeof(p));//p是一个指针变量,指针就是地址 地址的大小为:4/8 字节

	printf("%d\n", sizeof(p + 1));// p+1取到'b'的地址,还是地址 大小为:4/8 字节

	printf("%d\n", sizeof(*p));// *p p里面存放的是’a'的地址,*p取到'a' 大小为:1 字节

	printf("%d\n", sizeof(p[0]));// p[0] 等同于 *(p+0) 也就是*p 还是取到’a' 大小为:1 字节

	printf("%d\n", sizeof(&p));// &p 取到的是指针变量p的地址,是一个二级指针,还是地址,大小为:4/8 字节

	printf("%d\n", sizeof(&p + 1));// &p 取到的是指针变量p的地址,是一个二级指针 让二级指针+1 还是地址 大小为:4/8 字节

	printf("%d\n", sizeof(&p[0] + 1));// &p[0] 取到’a'的地址 让地址+1 取到‘b'的地址,还是地址 大小为:4/8 字节


	printf("%d\n", strlen(p));// p指向’a' p是‘a'的地址,从’a'开始计算 6

	printf("%d\n", strlen(p + 1));//  p指向’a' p是‘a'的地址,p+1取到‘b'的地址 从’b‘的地址开始计算 5

	printf("%d\n", strlen(*p));//*p 取到 ’a'  ASICC值为 97 把97当做地址 传过去 非法 err报错

    printf("%d\n", strlen(p[0]));// p[0] 取到‘a' 97当做地址,非法 err 报错

	printf("%d\n", strlen(&p));// &p 取到的是指针变量p的地址,是一个二级指针 从指针变量p的地址开始计算 随机值

	printf("%d\n", strlen(&p + 1));//&p 取到的是指针变量p的地址,是一个二级指针 &p+1 取到p地址后面的地址开始计算,随机值

	printf("%d\n", strlen(&p[0] + 1));//  &p[0] 取到’a'的地址 让地址+1 取到‘b'的地址  从’b‘的地址开始计算 5

	return 0;
} 




//第四题

int main()
{
	//数组名只有两种情况下表示整个数组(sizeof(数组名) 和 &数组名 )
	//其它情况下都表示首元素的地址
	//而二维数组是由多个一维数组 组成的,二维数组的行数决定了一维数组的个数
	//因为二维数组是由多个一维数组 组成的
	//所以二维数组可以看成是一个一维数组,而这个一维数组的元素都是一个一维数组
	/*二维数组的数组名表示首元素地址,而这个首元素地址便是第一行的那个一维数组的地址
	所以二维数组的其他情况下的数组名取到的是第一个一维数组的地址
	在传参的时候传过去的是一个一维数组的地址,用数组指针来接收*/

	//二维数组
	int a[3][4] = { 0 };

	printf("%zd\n", sizeof(a));//48 sizeof(数组名) 表示整个数组,大小为:48 字节

	printf("%zd\n", sizeof(a[0][0]));//4 a[0][0] 等同于 *(*(a+0)+0) 取到的是第一行第一个元素 大小为:4 字节

	printf("%zd\n", sizeof(a[0]));//16 a[0]取到的是第一行的数据,也就是一维数组,a[0]其实就是第一行一维数组的数组名,
								//	而数组名单独出现sizeof(数组名) 表示整个数组,
								//  而第一行一维数组有4个元素,都是整型,大小为:16 字节

	printf("%zd\n", sizeof(a[0] + 1));//4/8 a[0]表示第一行一维数组的数组名,数组名表示首元素地址,
									// a[0]+1,表示第一行第二个元素的地址,本质上是地址,大小为:4/8 字节

	printf("%zd\n", sizeof(*(a[0] + 1)));//4 a[0]+1表示第一行第二个元素的地址 *(a[0]+1) 表示第一行第二个元素的内容,是一个整数,大小为:4 字节

	printf("%zd\n", sizeof(a + 1));//4/8 a表示二维数组首元素地址,a+1指向数组后面的一片空间,还是地址,大小为:4/8

	printf("%zd\n", sizeof(*(a + 1)));//16 *(a+1) 等同于 a[1] 是第二行一维数组的数组名,sizeof(数组名) 表示整个数组:大小为:16 字节

	printf("%zd\n", sizeof(&a[0] + 1));//4/8 a[0]表示第一行一维数组的数组名,
									 //&数组名,取到的是整个数组的地址,让整个数组的地址+1 指向第二行数组 还是地址:大小为:4/8
	
	printf("%zd\n", sizeof(*(&a[0] + 1)));//16  a[0]表示第一行一维数组的数组名 &a[0]取到的是第一行一维数组的地址,
										// &a[0]+1 表示第二行一维数组的地址,*(&a[0]+1)取到的是第二行二维数组
										// *(&a[0]+1) 等同于 a[1]

	printf("%zd\n", sizeof(*a));//16 a表示首元素地址,也就是第一行一维数组的地址,对其解引用操作取到第一行一维数组

	printf("%zd\n", sizeof(a[3]));//16 a[3]是第四行的一维数组的数组名,sizeof(数组名)表示整个数组的大小:16 字节
								// 但因为没有对空间进行访问 所以它只是一个地址编号,不会发生越界

	return 0;
}

指针变量笔试题

第一题:

#include <stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	int* ptr = (int*)(&arr+1);
	printf("%d %d\n", *(arr + 1), *(ptr - 1));

	return 0;
}

程序的运行结果是什么?

解析:

答案是:2  5

 

1、arr数组名数字名表示首元素地址

     arr+1表示第二个元素的地址

    *(arr+1) 取到第二个元素的内容 2

2、&arr表示的是整个数组的地址,

     指针类型为:int (*)[5]一次可以访问5个整型的空间 

     让&arr+1跳过整个数组,让其指向数组后面的空间,它是数组指针

     再将其强制类型转换为(int*)的指针,一次只能访问4字节的空间

     此时再让ptr-1,取到的是数字5的地址,

     再对其解引用得到数字5

第二题:

#include <stdio.h>

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

解析:

答案是:  00 10 00 14

                00 10 00 01

                00 10 00 04

1、p是一个结构体类型的指针,让p+1是跳过整个结构体

      指针+1加的是其类型的大小,p是结构体类型,大小为20

      p+1起始就是让p的地址+20,,20转化成十六进制为14

      就是让0x100000加20,结果为 0x 00 10 00 14

2、将p强制类型转化成unsigned long 类型

      此时的p的内容被当成数值0x100000 

      让这个数值+1 得到另一个数值为:0x1000001

      %p打印的是数据原码的十六进制的形式

       因为正数的原码反码补码相同,

       所以结果依然是这个数值的十六进制形式

       而这个数值本来就是十六进制形式表示

       即结果为:0x 00 10 00 01

3、将结构体指针p强制类型转化为unsigned int* 类型

      让指针+1其实就是+上指针类型的大小

       此时p的类型为 unsigned int 类型,大小为:4字节

       让地址p+4 结果就是:0x 00 10 00 04

第三题:

#include <stdio.h>

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

return 0;
}

解析:

答案为:4 , 2

1、&a取到的是整个数组的地址

      &a+1指向的是数组后面的一片空间

      再让其强制类型转化成int*赋值给ptr

      此时ptr1也指向数组后面的一片空间

       ptr1能访问的空间大小为4字节

       ptr1[-1]等同于*(ptr1-1) 

       ptr1-1指向数组数值为4的位置

       再对其解引用取到指针指向的内容4

       用%x十六进制打印 十六进制的4 还是4

       所以结果为:4

 2、a数组名表示首元素地址,将其强制类型转换int型

      将首元素地址,当成数值看待,让数值+1

      然后在将数值+1强制转化成int*类型,再赋值给ptr2

      此时的ptr指向的是首元素1的第二个字节的位置

      因为当前机器是小端存储,1在存储的时候是:01 00 00 00

      紧接着后续存放的是 02 00 00 00

      再对ptr2解引用,int类型的指针一次访问4个字节的空间

      访问到的内容是:00 00 00 02

       因为当前是小端机器,在存取的时候按照 02 00 00 00

       的方式存取,即*ptr2结果为:02 00 00 00

       用%x十六进制打印 十六进制的2000000 还是2000000

       所以结果为:2000000

第四题:

#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);

return 0;
}

解析:

答案:1

 

二维数组在赋值的时候,数组里面有三个逗号表达式

逗号表达式的结果是最后一个表达式的结果

即二维数组a里面存放的元素为:

{{1,3},{5,0},{0,0}}

此二维数组是三个一维数组 组成的

a[0]实际上是第一行一维数组的数组名

a[0]数组名表示第一行一维数组首元素地址

第一行一维数组的首元素为数字1,

a[0]就是数字1的地址,

将数字1的地址赋值给整型指针变量p

p[0] 等同于 *(p+0) 也就是*p

*p对指针解引用取到它所指向的内容 取到数字1

结果为:1

第五题:

#include <stdio.h>
int main()
{
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]);

return 0;
}

解析:

答案:FFFFFFFC  -4

a是一个5行5列的数组

p是一个数组指针,指向的数组有4个元素 

数组名表示首元素地址

则a表示的是第一行的一维数组的地址

将一维数组的地址强制放进数组指针p里面

p指向的数组有4个元素,让p+1走的步长是4个整型的大小

由图可知,&p[4][2] - &a[4][2] 之间有4个元素 答案是-4

-4的原码:10000000 00000000 00000000 00000100

        反码:11111111 11111111 11111111 11111011

        补码:11111111 11111111 11111111 11111100

用十六进制:FF FF FF FC

则用%p打印:FFFFFFFC

用%d打印则是:-4

第六题:

#include <stdio.h>

int main()
{
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));

return 0;
}

解析:

答案: 10 ,  5

 

1、aa是一个2行5列二维数组

     &aa取到的是整个数组的地址

     &aa+1 执行数组后面的空间

     将&aa+1强制类型转化成(int*)类型的指针

     并赋值给ptr1,此时ptr1也指向&aa+1的地址

     让*(ptr1-1 ) 步长为4个字节

     此时ptr1-1是数值10的地址

     *(ptr1-1) 取到的是数值10

2、*(aa+1) 等同于 aa[1] 

aa[1]其实就是第二行一维数组的数组名

数组名表示首元素地址也就是数字6的地址

将数字6的地址赋值给ptr2 ptr2的类型是int

ptr2-1取到数字5的地址

*(ptr2-1)对其解引用取到数值5

第七题:

#include <stdio.h>

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);

	return 0;
}

解析:

答案:at

 

a数组名表示首元素地址

数组的首元素就是字符‘w’的地址

即a本质上是‘w’的地址的地址,其实是一个二级指针

将a赋值给pa此时pa也就是字符‘w’的地址的地址

让pa++,实际上是pa=pa+1,对指针+1的步长,是指针类型的大小

pa指向了第二个元素的地址,而数组的第二个元素为:‘a’的地址

*pa 再对pa解引用取到‘a’的地址

用%s打印,从‘a’的地址开始打印字符直到碰到\0结束

第八题:

#include <stdio.h>

int main()
{
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);

return 0;
}

解析:

答案:POINT

           ER

           ST

           EW

c数组里面存放四个元素,每个元素都是char*类型也就是字符指针

cp数组里面存放四个元素,每个元素都是char**类型,也就是二级指针

通俗讲:就是存放字符的地址的地址

cpp是一个三级指针变量

里面存放的是cp的首元素的地址

而cp的首元素是字符地址的地址是一个二级指针

1、(**++cpp)

      ++cpp取到的是cp数组第二个元素的地址

     先对cpp解引用取到cp数组第二个元素的内容

     内容是一个地址,而这个地址是字符地址的地址

     再对其进行解引用取到‘P’的地址

     用%s打印从‘p’地址开始打印到\0结束

     结果为:POINT

2、(*-- * ++cpp + 3)

      先++cpp 取到cp数组第三个元素的地址

      再*++cpp 解引用取到第三个元素的内容

      内容是字符'N'的地址的地址

      再进行--操作就是变成字符‘E’的地址的地址

      再进行* 解引用操作取到字符‘E’的地址

      再+3让字符‘E’的地址+3取到下一个字符‘E’的地址

      用%s打印从‘E’地址开始打印到\0结束

      结果为:ER

3、( *(cpp[-2] + 3))

      cpp[-2]等同于*(cpp-2) 

      cpp-2取到的是cp数组首元素的地址

      再对其解引用,取到的是字符‘F’的地址的地址

      在进行解引用取到的是字符‘F’的地址

      再让其+3 取到的是字符‘S’的地址

      用%s打印从‘S’的地址开始打印遇到\0结束

      结果为:ST

4、

      cpp[-1][-1] 等同于 *(*(cpp-1)-1)

      cpp-1取到cp数组第二个元素的地址

      再对其*解引用操作 取到字符‘P’的地址的地址

      再让地址-1取到字符‘N’的地址的地址

      再对其*解引用取到字符‘N’的地址

      再让其+1取到字符‘E’的地址

      用%s打印从‘E’的地址开始打印遇到\0结束

      结果为:EW

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/157730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网站让百度收录的技巧有哪些?网站在百度收录情况怎么查询

同样都是新上线的站点&#xff0c;为什么有的人是秒收&#xff0c;有的人可能要等很多时间才能收录&#xff0c;其实这些都是有技巧加快百度收录我们网站的。网站让百度收录的技巧有哪些&#xff1f;1、上线之前做好网站内容 我们在上线之前一定要做好充足的准备&#xff0c;这…

浏览器控制台接口学习

我们在做项目开发时&#xff0c;想知道一个功能调用了后台哪个接口&#xff0c;我们就可以在浏览器控制台中进行查看。 举一个例子&#xff0c;我们在看博客时&#xff0c;发现这一篇文章写的不错&#xff0c;我们在做点赞这个动作时&#xff0c;调用了哪个接口呢&#xff1f; …

linux 内存恒等映射

目录 arm64内存管理 恒等映射 页表定义&#xff0c;采用4级分页模型 创建页表 内存属性 从进程角度看&#xff0c;需要内存的地方 1、进程本身&#xff0c;代码段、数据段用来存储程序本身需要的数据 2、栈空间&#xff1a;用来保存函数调用关系、局部变量、函数参数、函…

在centos系统上安装mongodb数据库

在centos系统上安装mongodb数据库 本文章基于centos8系统; 如何查看当前系统是centos的那个版本 终端输入命令 cat /etc/redhat-release 开始安装官网当前的数据库版本6.0; 查看官方文档 创建 mongodb yum 源头,写入基本信息 vim /etc/yum.repos.d/mongodb-org-6.0.repo [mon…

手把手教你如何创建和美化图表,老板直接给我升职!

一图胜千言。说到图表&#xff0c;想必很多人都被网上酷炫的图表震惊过。比如下面这样的可视化图表&#xff0c;看起来&#xff0c;很高大上有没有。但是&#xff0c;拆解开来&#xff0c;就是由一个个基础图表演变而来的。所以可不要小瞧了基础图表的制作。今天我就教你如何用…

使用ORM方式查询Mongodb里的数据,再也不用记Mongodb的语法(ORM Bee)

使用ORM方式查询Mongodb里的数据,再也不用记Mongodb的语法&#xff08;ORM Bee)Mongodb的语法可读性差&#xff0c;要写复杂查询&#xff0c;要求技术能力高&#xff1b;Java驱动&#xff0c;还要使用另一种语法&#xff1b;学习成本太高了。可以使用ORM方式&#xff0c;轻松搞…

【redis6】第三章(五大常用数据类型)

redis命令列表&#xff1a;http://www.redis.cn/commands.html Redis键 set < key >< value >添加键值对 [rootlocalhost ~]# cd /usr/local/bin [rootlocalhost bin]# redis-server /etc/redis.conf [rootlocalhost bin]# redis-cli 127.0.0.1:6379> set k1 a…

电脑怎么恢复出厂设置?Win10系统恢复出厂设置的方法

电脑经常出现报错的情况&#xff0c;而且还有运行缓慢、卡顿的问题&#xff0c;这代表你的电脑可能出现了老化。想要恢复正常&#xff0c;你可以选择把电脑恢复到出厂设置&#xff0c;从而恢复到原始状态。电脑怎么恢复出厂设置&#xff1f;下面以Win10系统电脑为例&#xff0c…

CTK Plugin Framework插件框架学习--插件通信【事件监听】

文章目录一、前言二、事件三、类通信3.1、新建接收插件3.2、新建发送插件3.3、启用插件四、信号槽通信4.1、新建接收插件4.2、新建发送插件4.3、启用插件五、类通信和信号槽通信的区别六、插件依赖七、获取元数据一、前言 CTK框架中的事件监听&#xff0c;其实就是观察者模式&…

Dolphin Streaming实时计算,助力商家端算法第二增长曲线

丨目录&#xff1a;1.背景2.业务问题3.业界解决方案4.技术方案5.应用示例6.业务收益7.总结1. 背景随着业务朝向精细化经营增长&#xff0c;阿里妈妈商家端营销产品更加聚焦客户投放体验&#xff0c;旨在帮助商家提升经营效果&#xff0c;在变化的市场中找到确定增长。近年来&am…

【OpenGL学习】OpenGL介绍

一、OpenGL是什么&#xff1f; 在早期一般认为OpenGL是一个API(Application Programming Interface, 应用程序编程接口)&#xff0c;包含了一系列可以操作图形、图像的函数。然而&#xff0c;OpenGL本身并不是一个API&#xff0c;它仅仅是一个由Khronos组织制定并维护的规范(S…

商城模式“分享购”意味着什么?关键逻辑是什么?

商城模式“分享购”近期炽手可热的卖家打赏模式电子商务平台&#xff0c;根据申请注册交易赠予贡献度&#xff0c;推动者每日权重计算分派领到固定不动积分兑换数量空投物资&#xff0c;积分兑换前去出售买卖转现&#xff0c;店家根据选购积分兑换完成对客户的交易打赏主播&…

【遥感综述】

遥感综述小集合 Image fusion meets deep learning: A survey and perspective&#xff08;张浩&#xff0c;马佳义&#xff09; Sharpening fusion 多光谱图像锐化和高光谱图像锐化是两种典型的锐化融合任务。 Multi-spectral sharpening多光谱锐化 多光谱锐化是将低空间…

Android开发必修—Activity,View,Window三者之间的密切联系【深度解析】

简介 Activity就像工匠&#xff0c;Window就像是窗户&#xff0c;View就像是窗花&#xff0c;LayoutInflater像剪刀&#xff0c;Xml配置像窗花图纸。 Android根据他们不同的职能让他们各斯其活&#xff0c;同时也相互配合展示给我们灵活、精致的界面。 一张图理清所有层级关系&…

量子计算机的推出会影响网络安全吗

在谈量子计算机之前&#xff0c;首先得了解什么是量子计算机。量子计算机是一类遵循量子力学规律进行高速数学和逻辑运算、存储及处理量子信息的物理装置。当某个装置处理和计算的是量子信息&#xff0c;运行的是量子算法时&#xff0c;它就是量子计算机。量子计算机在分析大量…

飞凌OK3568-C嵌入式Linux开发板开箱体验

本篇来介绍一款具有AI计算能力的Linux开发板&#xff1a;OK3568-C。 1 OK3568-C介绍 OK3568-C是飞凌嵌入式设计的一款开发板&#xff0c;板子的包装如下&#xff0c;盒子内有两层&#xff0c;上层是开发板&#xff0c;下层是配件。 1.1 核心板介绍 开发板的SOC采用Rockchip的…

MySQL进阶:索引的使用及理解

MySQL索引前言什么是索引?索引的优缺点?MySql索引添加索引的sql语句添加PRIMARY KEY&#xff08;主键索引&#xff09;添加UNIQUE(唯一索引)添加INDEX(普通索引)添加FULLTEXT(全文索引)添加多列索引索引的底层数据结构哈希索引BTree树索引为什么索引会提高查找速度?最左前缀…

数据结构与算法2—链表

1. 链表 线性表的链式存储结构就是用一组任意的存储单元&#xff08;可以是不连续的&#xff09;存储线性表的数据元素。采用链式存储结构的表示的线性表简称链表。链式存储方式可用于表示线性结构&#xff0c;也可用于表示非线性结构。 链表通常有两个域 data域——存放结点…

北大硕士LeetCode算法专题课--递归和回溯

算法专题课 北大硕士LeetCode算法专题课-栈、队列相关问题_骨灰级收藏家的博客-CSDN博客 北大硕士LeetCode算法专题课--链表相关问题_骨灰级收藏家的博客-CSDN博客 北大硕士LeetCode算法专题课-查找相关问题_骨灰级收藏家的博客-CSDN博客 北大硕士LeetCode算法专题课-字符串…

一.【linux】常用操作命令

目录 1 . 查看当前登录系统用户信息 【who】 2 . 查看终端用户whoami 3 . 查看日期date 4 . 查看系统信息uname 5 . 日历cal 6 . 计算器bc 8 . 显示或修改计算机主机名的命令hostname 9 . 在显示器上显示文字的命令echo 10 . 清除计算机屏幕上的信息命令clear 11 . 查…