C语言复杂表达式与指针高级

news2024/10/5 14:46:25

一、指针数组与数组指针

1.指针数组VS数组指针

(1)指针数组:实质是一个数组,因为这个数组中传参的内容全部是指针变量。

(2)数组指针:实质是一个指针,这个指针指向一个数组

2.分析指针数组与数组指针的表达式

注意点:符号的优先级有什么作用?其实是决定当2个符号一起作用的时候决定哪一个符号先运算,哪一个符号后运算。

【】,.   ,->这几个优先级比较高

(1)int *p[5];

核心:p

第一个结合:p[5]---》【数组的(【】)优先级比指针(*)高】

第二个结合:*p[5]---》整一个指针数组

因为p先跟【】组合所以是数组,在跟*结合所以是指针,合起来就是指针数组【先结合起来的放在后面】

数组有5个元素大,数组中的元素都是指针,指针指向的元素类型是int类型的,整个符号是一个指针数组。

(2)int (*p)[5]

核心:p---》p是一个指针

第一个结合:(*p)【】--》数组指针

p先和*结合,所以是指针,在和【】结合,所以是数组指针【先结合起来的放在后面】

指针指向一个数组,数组有5个元素,数组中存的元素是int类型,是一个数组

(3)Int *(p[5])

核心:p

第一个结合:p[5]--->数组

第二个结合:* (p[5])---》是指针数组

因为p先跟【】组合所以是数组,在跟*结合所以是指针,合起来就是指针数组【先结合起来的放在后面】

数组有5个元素大,数组中的元素都是指针,指针指向的元素类型是int类型的,整个符号是一个指针数组。

(4)总结

(1)一般规律,Int *p(p是一个指针)

        int p[5](p是一个数组)

(2)我们在定义一个符号时,关键在于:首先搞清楚你定义的符号是谁

        第一步:找核心;

        第二步:看谁和核心最近,谁根核心结合;

        第三步:以后继续向外结合

(3)如果核心与*结合,表示核心是指针;如果核心和【】结合,表示核心是数组;如果核心和()结合,表示核心是函数

(4)用一般规律

3.总结

1.优先级和结合性是分析符号意义的关键

2.学会逐层剥离的方法

找到核心后从内向外层进行结合,结合之后可以把已经结合的部分当成一个整体,再去和整体外部的继续进行结合

二、函数指针与typedef

1.函数指针的实质(还是指针变量-->存放函数地址)

(1)函数指针的实质还是指针,还是指针变量,本身占4字节(在32位系统中,所有的指针都是4字节)

(2)函数指针,数组指针,普通指针之间并没有本质区别,区别在于指针指向的大小是什么东西

(3)函数的实质是一段代码,这一段代码在内存中是连续分布的(一个函数的大括号括起来的所有语言将来编译出来生成的可执行程序是连续的),所以对应函数来说很关键的就是函数中的第一句代码的地址,这个地址就是所谓的函数地址,在c语言中用函数名这个符号来表示。

(4)结合函数的实质,函数指针其实就是一个普通变量,这个普通变量的类型是函数指针变量类,它的值就是某一个函数的地址(页就是它的函数这个符号在编译器中对应的值)

2.函数指针的书写和分析方法

(1)C语言本身是强类型语言(每一个变量都有自己的变量类型),编译器可以帮我们做严格的类型检查

(2)所有的指针变量类型其实本质都是一样的,但是为什么在c语言中要去区分他们,写法不一样呢(比如int类型指针就写int *p;数组指针就写int (*p)[5],函数指针就写的更复杂)

(3)假设我们有个函数是:

        void func(void),

        对应的函数指针;void (*p)(void)

        类型是void (*)(void)

 (4)函数名和数组名最大的区别就是:函数名做右值时加不加&效果和意义都是一样的;

                    pFunc = func1;//左边是一个函数指针变量,右边是一个函数名
                    pFunc = &func1;//&func1和func1做右值一模一样

          但是数组名做右值时加不加&意义就不一样。

void func1(void) {
	printf("test");
}

void main(){

	void (*pFunc)(void);//变量名是:pFunc
						//类型是:void (*) (void)
	pFunc = func1;//左边是一个函数指针变量,右边是一个函数名
	pFunc = &func1;//&func1和func1做右值一模一样
	func1();//用函数指针来解调用函数
}

(5)写一个复杂的函数指针的实例:比如函数是strcpy函数

                                char *strcpy(char *dest, const char *src);

对应的函数指针是:char* (*pFunc)(char *dest,const char *src)

	//直接使用函数指针调用strcpy
	char a[5] = { 0 };
	//char *strcpy(char *dest, const char *src);--->函数原型
	char* (*pFunc)(char*, const char*);//变量名为:pFunc
	pFunc = strcpy;
	pFunc(a, "abc");
	printf("a=%s\n", a);

3.typedef关键字的用法

(1)typedef是C语言中一个关键字,作用是用来定义(或者叫重命名类型)

(2)c语言中类型一共有2种:

        第一种是编译器定义的原生类型(基础数据类型)

        第二种是用户自定义类型,不是语言自带是程序员自己定义的

(3)typedef是将自定义类型进行重命名

(4)注意点:

        typedef是给类型重命名,也就是说typedef加工出来都是类型,不是变量。

//这句话重命名了一种类型,这个新类型叫pType,类型是:char* (*)(char*, const char*)
typedef char* (*pType)(char*, const char*);


//函数指针数组
typedef char* (*pType[1])(char*, const char*);


void main(){

	char* (*p1)(char*, const char*);
	char* (*p2)(char*, const char*);

	pType p3;//等价于char* (*p3)(char*, const char*);
	pType p4;
}

三、函数指针实战

1.用函数指针调用执行函数

(1)最简单的函数指针来调用函数的示例上面已经讲解

(2)用函数指针指向不同的函数来实现同一个调用指向不同的结果

(3)比如C++和java等面向对象的语言,就会知道面向对象三大特征有一个多态。多态就是同一个指向实际结果不一样,跟我们这里看到的现象其实是一样的。

#include<stdio.h>
#include <string.h>

//定义了一共类型pFun,这个函数指针类型指向一种特点参数列表和返回值的函数
typedef int (*pFun)(int, int);

int add(int a, int b){
	return a + b;
}

int sub(int a, int b) {
	return a - b;
}

int multiply(int a, int b) {
	return a * b;
}

int divide(int a, int b) {
	return a / b;
}

void main(){

	pFun p1 = NULL;//函数指针
	char c = 0;
	printf("请输入操作数据类型:");
	scanf("%c", &c);
	switch (c) {
	case '+':
		p1 = add;
		break;
	case '-':
		p1 = sub;
		break;
	case '*':
		p1 = multiply;
		break;
	case '/':
		p1 = divide;
		break;
	default:
		p1 = NULL;
		break;
	}
	int a, b;
	printf("请输入2位数字");
	scanf("%d %d", &a, &b);
	int result = 0;
	result=p1(a, b);
	printf("a=%d,b=%d,c=%d", a, b, c);


}

刚才调试可以得到很多信息:

(1)当程序出现段错误的时候,第一步先定位段错误。定位的方法就是在可疑加打印消息,从而锁定导致段错误的语句,然后集中分析这句话为什么会错误

(2)Linux中命令行默认是行缓冲的,意思是当我们程序printf输出的时候,LInux不会一个字一个字的输出我们的内容。而是将其缓冲起来放在缓冲区等一行准备完再一次性把一行全部输出(为了效率)。Linux判断一行有没有完的依据就是换行符'\n'

(window中换行符是\r\n

Linux中的换行符是\n

ios中的换行符是\r)

也就是说你printf再多,最后没有遇到\n(或者中断程序,或者缓冲区满)都不会输出而会不断缓冲,这时候你是看不到内容输出。因此,再每一个printf打印语句(尤其是用来做调试的printf)后面一定要加\n,否则可能导致几点:

(3)关于再linux命令行下用scanf写交互性代码的问题,想说以下几点:

1.我们用户再输入内容时结尾都会用\n结尾,但是程序中scanf的时候都不会去接收最后的\n,导致这个回车保存再标志输入中。下一次再scanf时就会被拿出来,就是导致你真正想拿的那个数反而没有机会拿,导致错误。

printf("请输入a=%d b=%d\n",a,b);
do{
    scanf("%c",&c);//将上面的换行符读取走
}while((c=='\n') || (c=='\r));

2.结构体内嵌函数指针实现分层

总结:

(1)本节和上节实际完成同一个任务,但是采用了不同的程序架构

(2)对于简单问题来说,上节的不分层反而容易理解,反而简单,本节的分层代码不好理解,看起来有点把简单问题复杂化。原因在于我们这个问题本身确实是简单问题,而简单问题应该简单处理。我们为什么还要这样做?

(3)分层之后上层为下层提供服务,上层写的代码是为了在下层中被调用

(4)上层注重注重业务逻辑,与我们最终的目标相直接关联,而没有具体干活的函数。

(5)下层注重实际干活的函数,注重为上层填充变量,并且将变量传递给上层中的函数(其实就是调用上层提供的接口函数)来完成任务。

cal.c

#include<stdio.h>
#include"framwork.h"

int main(){
	int ret=0;
	struct cal_t myCal;
	myCal.a=12;
	myCal.b=3;
	myCal.p=div;
	ret=calculator(&myCal);
	printf("ret=%d",ret);
	return 0;
}

framwork.c

#include<framwork.h>

int add(int a, int b){
	return a + b;
}

int sub(int a, int b) {
	return a - b;
}

int multiply(int a, int b) {
	return a * b;
}

int divide(int a, int b) {
	return a / b;
}

//计算器函数
int  calculator(const struct cal_t *p){//这里我们使用的是结构体指针
	//表示将结构体中的值赋值给变量
	return p->p(p->a,p->b);
}



framwork.h

#ifndef __CAL_H__
#define __CAL__H__

//定义了一共类型pFun,这个函数指针类型指向一种特点参数列表和返回值的函数
typedef int (*pFun)(int, int);

//结构体是用来做计算器,计算器工作时需要的原材料
struct cal_t{
	int a;
	int b;
	pFunc p;
}

//函数原型声明
void calculator(const struct cal_t *p);

四、在论typedef

1.c语言的2种类型:内建类型与用户自定义类型

(1)内建类型ADT,自定义类型UDT

2.typedef定义类型而不是变量

(1)类型是一个数据模块,变量是一个实在的数据。类型是不占内存,而变量是占内存的

(2)面向对象的语言中:类型就是类class,变量就是对象

3.typedef VS #define的区别

宏定义 (define) 和 typedef 的区别 | 编程指北

typedef 旧的 新的

#define 新的 旧的

typedef char *pChar;//表示将char*重命名为pChar
#define pChar char*;

4.typedef和结构体

(1)结构体在使用时都是先定义结构体,然后再使用结构体去定义变量

(2)C语言规定,结构体类型使用时必须使用 【struct 结构体类型名 结构体变量名;】这样来定义

//结构体类型的定义
struct student {
	char name[20];
	int age;
};

//定义了一个结构体类型,这个类型有2个名字
//第一个名字:struct student
//第二个名字:student_t
typedef struct student {
	char name[20];
	int age;
}student_t;

//两个名字一样也可以
//第一个名字:struct student
//第二个名字:student
typedef struct student {
	char name[20];
	int age;
}student;

int  main(){
	struct student s1;//struct stduent是类型,s1是变量
	s1.age = 12;

	student_t s2;

	student s3;

	//student s2;//不能这样定义一个结构体变量

	return 0;

}

(3)使用typedef一次定义2个类型,分别是结构体变量类型和结构变量指针

结构体指针类型:struct teacher *   pTeacher

//我们一次定义了两个类型
//第一个是结构体类型,有2个名字:struct teacher  teacher
//第二个是结构体指针类型,有2个名字:struct teacher*   pTeacher
typedef struct teacher {
	char name[23];
	int age;
	int mager;
}teacher,*pTeacher;


	teacher t1;
	t1.age = 23;
	pTeacher p1 = &t1;
	printf("teacher age=%d\n", p1->age);

5.typedef与const

(1)typedef int* PINT:永远只能修改变量的值,不能修改变量本身

(2)typedef const int *CPINT:可以修改变量本身,但是不能修改变量的值

1.typedef int* PINT;const PINT p2;相当于int *const p2;【不能修改p2的值】

typedef int* PINT;//将int * 重命名为PINT

//注意区分
//const int *p和int *const p是不同的
//【const int *p】:表示p指向的变量是不可以变
//【int *const p】:表示p本身不可以改变

	int a = 23;
	int b = 11;
	PINT p1 = &a;
	//本来翻译过来是这样的:const int *p2 【指向的值不能改变】
	//但是测试说明:p2所指向的值是可以改变的
	const PINT p2= &a;
	*p2 = 33;
	printf("*p2=%d",* p2);
	p2 = &b;//此处报错,p2本身不能被修改

2.typedef int* PINT;cPINT const p2;相当于int *const p2;【不能修改p2的值】


typedef int* PINT;//将int * 重命名为PINT

//注意区分
//const int *p和int *const p是不同的
//【const int *p】:表示p指向的变量是不可以变

	int a = 23;
	int b = 11;
	PINT p1 = &a;
	//本来翻译过来是这样的:const int *p2 【指向的值不能改变】
	//但是测试说明:p2所指向的值是可以改变的
	PINT const p2= &a;
	*p2 = 33;
	printf("*p2=%d",* p2);
	p2 = &b;//此处报错,p2本身不能被修改
	

如果确实想要得到const int *p【可以修改p本身】,这种效果,只能使用typedef const int *CPINT;CPINT p1;

//此时等价于
// int *cosnt p;【表示p本身不能改变】
typedef const int* CPINT;
	int a = 12;
	int b = 23;
	CPINT p = &a;
	*p = 22;//报错,此时不能修改p所指向的值
	p = &b;

6.使用typedef的意义

(1)简化类型的描述

char *(*)(char *,char *);                        typedef char *(*pFun)(char *,char *)

(2)很多编程体系下,人们倾向于不适应int,double等C语言内建类型,因为这些类型本身和平台是相关的(比如int再16位机器上是16位的,再32位机器上就是32位),所以很多程序使用自定义的中间类型再做缓冲。

用size_t来替代int

typedef int size_t;

(3)STM32库中全部使用了自定义类型

五、二重指针

1.二重指针与普通一重指针的区别

(1)从本质上来说,二重指针和一重指针本质都是指针变量,指针变量的本质就是变量

(2)一重指针变量和二重指针变量本身都占4字节内存空间

	char** p1;//二重指针
	char* p2;//一重指针

	printf("sizeof(p1)=%d", sizeof(p1));//4
	printf("sizeof(p2)=%d", sizeof(p2));//4

2.二重指针的本质

(1)二重指针本质也是指针变量,和一重指针的差别就是他指向的变量类型必须是一个一重指针二重指针其实也是一种数据类型,编译器再编译时会根据二重指针的数据类型来做静态类型检查,一旦发现允许是数据类型不匹配编译器就会报错。

(2)一重指针完全可以做二重指针做的事情。

3.二重指针的用法

(1)二重指针指向一重指针的地址

	char** p1;//二重指针
	char* p2;//一重指针

	p1 = &p2;//p2本身是char *类型的,再取地址变成 char **类型的和p相同

(2)二重指针指向指针数组

	int* p1[2];
	int* p2;
	int** p3;

	//p1 = p2;//报错

	//p1是指针数组名,本质是数组名,数组名做右值表示数值首元素首地址
	//数组的元素就是int*类型,所以p1做右值就表示一个int *类型
	//变量的地址,所以p1就是一个int类型的变量的指针
	//所以他指向一个二重指针int **;
	p3 = p1;

(1)实践编程中二重指针用的比较少,大部分时候就是和指针数组纠结起来。

(2)实际编程中有时候在函数传参时为了通过函数内部改变外部的一个指针变量,会传这个指针变量的地址(也就是二重指针)进去。

void func(int** p) {
	*p = (int*)0x123456;
}

int  main(){


	int a = 4;
	int* p = &a;//此时p指向a
	printf("p=%p\n", p);
	func(&p);//此时在func内部将p指向了其他地方
	printf("p=%p\n", p);
	*p = 23;//此时p指向0x123456,但是这个地址是不允许访问的,所以出现段错误
	
}

4.二重指针与数组指针

(1)二重指针,数组指针,结构体指针,一重指针,普通变量的本质都是相同的,都是变量

(2)所有的指针变量的本质都是相同的,都是4字节。都是用来指向别的东西的,不同类型的指针变量只是可以指向的(编译器允许你指向的)变量类型不同。

(3)二重指针就是:指针数组指针

六、二维数组

1.二维数组的内映像

(1)一维数组在内存中的连续分布的多个内存单元组成的,而二维数组在内存中也是连续分布的多个内存单元组成的

(2)从内存角度来看,一维数组和二维数组没有本质区别

2.二维数组的维数

3.二维数组的下标式访问和指针式访问

4.二维数组的应用和更多维数组

七、二维数组的运算和指针

1.指针指向二维数组的数组名

(1)二维数组的数组名表示二维数组的第一位数组中首元素(也就是第二维的数组)的首地址

(2)二维数组的数组名a等同于&a[0],这个和一维数组的符号含义是相符的

(3)用数组指针来指向二维数组的数组名类型是匹配的

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

	//int* p1 = a;//报错---类型不匹配
	//int** p2 = a;//报错---类型不匹配

	int(*p3)[3] ;//类型匹配
	p3 = a;	//数组指针,指针指向一个数组,数组有2个int类型元素
			//a是二维数组的数组名,作为右值表示二维数组第一维的数组
			//的首先元素的首地址,等同于&a[0]

	printf("a[0][1]=%d\n", *(*(p3 + 0) + 1));
	printf("a[1][1]=%d\n", *(*(p3 + 1) + 1));

2.指针指向二维数组的第一维

(1)用int *p来指向二位数组的第一维a[i]

	//指针指向二维数组的第一维
	int a[2][5] = { {1,2,3,8,9},{4,5,6,10,11} };
	
	//&a[0]:表示第一维的地址
	//int* p4 = &a[0];//报错
	int* p4 = a[0];//a[0]表示二维数组的第一维的第一个元素,相当于是
				//第二维的整体数组的数组名。数组名又表示数组元素
				//首地址,因此a[0]等同于&a[0][0]
	//等价于
	int* p5 = &a[0][0];
	printf("a[0][4]=%d", *(p5 + 4));

	//a[1]等价于&a[1][0]
	int* p6 = a[1];//此时指向第一维的第二个元素
	printf("a[1][3]=%d", *(p6 + 3));

3.指针指向二维数组的第二维

(1)二维数组的第二维元素其实就是普通变量了(a[1][1]其实就是int类型的7),已经不能用指针类型和它相互赋值

(2)除非int *p=&a[i][j],类似于指针指向二维数组的第一维

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

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

相关文章

C语言,打印指定大小的X

要打印一个X&#xff0c;无非是在一个二维数组一个矩形中操作&#xff0c;将不是X的部分赋值为空格字符&#xff0c;将是X部分打印为*字符。 矩形的边长就是输入的n&#xff0c;由于矩形的边长是不固定的&#xff0c;所以要找到应该被赋值为*的坐标之间有什么数学关系。 以矩…

宏电股份AI BOX新产品首次亮相2023中国移动全球合作伙伴大会,以创新性AI、5G技术推动数实共生

10月11-13日&#xff0c;2023中国移动全球合作伙伴大会在广州开幕&#xff0c;本次大会以“算启新程&#xff0c;智享未来”为主题&#xff0c;作为中国移动多年来的重要合作伙伴&#xff0c;宏电股份AI BOX新产品在大会上首次精彩亮相&#xff0c;并重点展示了5G Redcap工业智…

格雷码加相移三维重建

之前所做的三维重建系统基本上都是基于多频率外差 的方法 &#xff08;交流方式可以点这个链接&#xff09;&#xff0c;最近整理了一下格雷码加相移的算法&#xff0c;与多频外差相比格雷码在对反光物体的重建效果稍微好一点&#xff0c;也可以投诉更少的图像 。采用6介互补格…

Python使用Selenium库如何绕过Cloudflare验证,网页请确认你是不是机器人

大家好&#xff0c;我是淘小白~ 前段时间使用selenium库写chatGPT的脚本&#xff0c;遇到过一个问题&#xff0c;那就是cloudflare的机器验证&#xff0c;让你点击确认不是机器人&#xff0c;这个问题最后找人解决掉了&#xff0c;我也是百度了很久没找到答案&#xff0c;B站找…

053:mapboxGL中sources的6种类型及各类型的示例代码

第053个 点击查看专栏目录 本篇文章是mapbox的source的归纳总结。 mapbox中 sources 是什么 sources:数据源集合(必填,用于包含一系列数据源 source,这些数据源提供了在地图上显示的数据) sources 是对象 {} 的形式,其属性名就是 数据源的名称(或者说 数据源的 id),…

网络基础初谈

0.一些无关紧要的心里话 ​ 一转眼学习计算机知识已经一年多了&#xff0c;中间起起伏伏&#xff0c;断断续续&#xff0c;但还算好也是坚持到了今天&#xff0c;之所以把这些基础知识写成一个系列&#xff0c;一方面方便知识巩固&#xff0c;另一方面至少还有三三两两的几个朋…

Linux命令之chpasswd命令

一、chpasswd命令简介 chpasswd命令用于同时更改多个用户的密码。它可以从标准输入或指定的文件中读取用户名和密码的组合&#xff0c;并将其应用于系统中的用户。chpasswd命令通常用于批量更改用户密码&#xff0c;特别是在自动化脚本或批处理任务中&#xff0c;该命令需要roo…

ERP系统供应商协同:优化企业供应链管理

一、ERP系统供应商协同的概念和功能 供应商协同是指在供应链中&#xff0c;企业与供应商之间通过ERP系统进行紧密合作和信息共享&#xff0c;实现供应链各个环节的协调和优化。ERP系统供应商协同功能涉及以下方面&#xff1a; 1. 供应商管理&#xff1a;ERP系统提供完善的供应…

华为云云耀云服务器L实例评测|windows系统3389防爆破之安全加固教程

为什么要选择华为云云耀云服务器L实例&#xff1a; 华为云在全国范围内建立了多个数据中心&#xff0c;这些数据中心之间相互冗余&#xff0c;以确保高可靠性和可用性&#xff0c;用户可以选择最适合的区域来部署应用程序&#xff0c;以实现更好的性能和延迟。 相对于传统的物…

选择什么电容笔比较好?平板手写笔推荐

由于苹果Pencil的热销&#xff0c;让华国内市场上&#xff0c;也出现了不少的平替式电容笔&#xff0c;这些产品&#xff0c;有好有坏&#xff0c;价格也很公道。不过&#xff0c;也有很多产品的价格都很平价。我是一个拥有多年经验的数码发烧友&#xff0c;在前几年就开始用上…

docker安装和docker安装RabbitMQ

docker安装 执行命令&#xff0c;先查看是否有Docker docker --version 如果想要删除&#xff1a;yum -y remove docker-ce 如果没有需要安装&#xff1a; 1.执行命令&#xff0c;实现Docker安装 yum install -y yum-utils yum-config-manager --add-repo http://mirrors.…

数组模拟堆实现堆排序

文章目录 QuestionIdeasCode Question 输入一个长度为 n 的整数数列&#xff0c;从小到大输出前 m 小的数。 输入格式 第一行包含整数 n 和 m 。 第二行包含 n 个整数&#xff0c;表示整数数列。 输出格式 共一行&#xff0c;包含 m 个整数&#xff0c;表示整数数列中前 m …

如何选择安全可靠的跨网文件安全交换一体机?

各行各业为了保护核心数据&#xff0c;绝大多数企业采取的第一个步骤是将企业内网与互联网进行隔离&#xff0c;将内部数据“困在”内网&#xff0c;同时也能够有效屏蔽外部网络攻击的风险。较大规模的企业&#xff0c;比如金融、政府、集成电路等行业机构&#xff0c;还可能对…

UE5----使用C++的项目重新打开后东西丢失

最近开始学习c编写代码&#xff0c;发现在场景里放置了Actor后&#xff0c;第二天打开项目&#xff0c;场景里边的放的球啊啥的东西没有了&#xff0c;蓝图类也丢失了父类。 解决方案&#xff1a; 不在Epic里打开虚幻引擎&#xff0c;在VS中打开。点击这个小绿三角&#xff0…

河北吉力宝:多维发力走创新智能鞋业道路

在快速发展的时代潮流中&#xff0c;智能科技正在改变我们的生活方式&#xff0c;消费者的选择更加多元化&#xff0c;以及制鞋行业同质化竞争严重等多重不利因素的影响&#xff0c;我国制鞋行业竞争加剧&#xff0c;各制鞋企业也在不断探索新市场&#xff0c;进一步拓展市场空…

京东数据分析:2023年下半年母婴市场各大细分赛道消费趋势盘点!

于今天的新生代父母而言&#xff0c;在诸多消费观念被改变的当下&#xff0c;新生父母们在育儿上更强调精细化&#xff0c;在这种情况下&#xff0c;母婴市场的消费升级已是大势所趋。不过&#xff0c;在如今收入增速整体放缓的背景下&#xff0c;各细分赛道的消费升级都出现了…

文心大模型4.0正式发布!来看看这届百度世界有啥亮点

今天&#xff0c;2023百度世界大会开幕了&#xff0c;大家都关注了吗&#xff1f;本次大会有很多亮点&#xff0c;我先摘一些和大家分享。 李彦宏现场做「手把手教你做AI原生应用」的分享&#xff0c;百度很多产品通过大模型进行了重构。文心大模型4.0重磅发布&#xff0c;综合…

mac读写硬盘的软件Tuxera NTFS2023免费版下载

Mac用户在使用NTFS格式移动硬盘时&#xff0c;会遇到无法写入硬盘的情况。要想解决无法写入的问题&#xff0c;很多人选择使用Mac读写软件。面对市面上“众多”的读写硬盘软件&#xff0c;用户应该怎么选择呢&#xff1f;初次接触移动硬盘的伙伴可能不知道移动硬盘怎么和电脑连…

短视频矩阵剪辑系统源码

短视频剪辑矩阵系统开发源码----源头搭建 一、源码技术构建源码部署搭建交付之---- 1.需要协助系统完成部署、接口全部正常接入、系统正常运行多久&#xff1f;7个工作日 2.需要准备好服务器以及备案域名 3.短视频SEO模块一年项目带宽&#xff0c;带宽最低要求10M&#xff0c;…

基于Java的交通事故档案管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…