c语言 指针_C 语言指针详解

(给CPP开发者加星标,提升C/C++技能)

作者:C语言与CPP编程 / 自成一派123(本文来自作者投稿)

1为什么使用指针

假如我们定义了 char a=’A’ ,当需要使用 ‘A’ 时,除了直接调用变量 a ,还可以定义 char *p=&a ,调用 a 的地址,即指向 a 的指针 p ,变量 achar 类型)只占了一个字节,指针本身的大小由可寻址的字长来决定,指针 p 占用 4 个字节。

但如果要引用的是占用内存空间比较大东西,用指针也还是 4 个字节即可。

  • 使用指针型变量在很多时候占用更小的内存空间。

变量为了表示数据,指针可以更好的传递数据,举个例子:

第一节课是 1 班语文, 2 班数学,第二节课颠倒过来, 1 班要上数学, 2 班要上语文,那么第一节课下课后需要怎样作调整呢?方案一:课间 1 班学生全都去 2 班, 2 班学生全都来 1 班,当然,走的时候要携带上书本、笔纸、零食……场面一片狼藉;方案二:两位老师课间互换教室。

显然,方案二更好一些,方案二类似使用指针传递地址,方案一将内存中的内容重新“复制”了一份,效率比较低。

  • 在数据传递时,如果数据块较大,可以使用指针传递地址而不是实际数据,即提高传输速度,又节省大量内存。

一个数据缓冲区 char buf[100] ,如果其中 buf[0,1] 为命令号, buf[2,3] 为数据类型, buf[4~7] 为该类型的数值,类型为 int ,使用如下语句进行赋值:

*(short*)&buf[0]=DataId;
*(short*)&buf[2]=DataType;
*(int*)&buf[4]=DataValue;
  • 数据转换,利用指针的灵活的类型转换,可以用来做数据类型转换,比较常用于通讯缓冲区的填充。

  • 指针的机制比较简单,其功能可以被集中重新实现成更抽象化的引用数据形式

  • 函数指针,形如: #define PMYFUN (void*)(int,int) ,可以用在大量分支处理的实例当中,如某通讯根据不同的命令号执行不同类型的命令,则可以建立一个函数指针数组,进行散转。

  • 在数据结构中,链表、树、图等大量的应用都离不开指针。

2 指针是什么?

操作系统将硬件和软件结合起来,给程序员提供的一种对内存使用的抽象,这种抽象机制使得程序使用的是虚拟存储器,而不是直接操作和使用真实存在的物理存储器。所有的虚拟地址形成的集合就是虚拟地址空间。

内存是一个很大的线性的字节数组,每个字节固定由 8 个二进制位组成,每个字节都有唯一的编号,如下图,这是一个 4G 的内存,他一共有 4x1024x1024x1024 = 4294967296 个字节,那么它的地址范围就是 0 ~ 4294967296 ,十六进制表示就是 0x00000000~0xffffffff ,当程序使用的数据载入内存时,都有自己唯一的一个编号,这个编号就是这个数据的地址。指针就是这样形成的。

9a01084c397736eaac357ca80778bbb5.png
1
#include 

int main(void)
{
    char ch = 'a';
    int  num = 97;
    printf("ch 的地址:%p\n",&ch);   
    //ch 的地址:00BEFDF7
    printf("num的地址:%p\n",&num);  
    //num的地址:00BEFDF8
    return 0;
}
e54ed66576f31cb740c3aa399cc32b77.png
085083f770a17abcf7335625e3136ed5.png

指针不仅可以表示变量的地址,还可以存储各种类型数据的地址,指针变量是用来保存这些地址的变量,与数组类似,依据地址存放的数据类型,指针也分为 int 指针类型,  double 指针类型, char 指针类型等等。

综上,指针的实质就是数据在内存中的地址,而指针变量是用来保存这些地址的变量

指针变量 和 指向关系

用来保存 指针 的变量,就是指针变量。如果指针变量p保存了变量 num的地址,则就说:p指向了变量num,也可以说p指向了num所在的内存块,指针变量pp指向了p所在的内存块,以下面为例:

#include 

int main(void)
{
  int num = 97;
  char ch = 'a';

  int *p = & num;
  int **pp = &p;
  char *p1 = & ch;

  printf("num 的地址:%p\n",&num);   
  printf("指针p的值:%p\n",p);   
  printf("指针p的地址:%p\n",&p);  
  printf("指针pp的值:%p\n",pp); 
  printf("ch 的地址:%p\n",&ch);  

  return 0;
}
77bd4449707e5ff329b5423e18b44c87.png
运行结果
  • int型的num值为97占4个字节,内存地址为:0113F924char 型的ch('a')值为97占1个字节,内存地址为:0113F91B
501df2871d0166bbd4be4d62e9da6fec.pngint型占4个字节
a6ac2befb1fe4eb8c26a163e8fab92cd.png

char型占1个字节

  • num的地址为:0113F924num的值为 97 ,指针 p 指向 num 的内存块,指针 p 地址为:0113F90Cp的内存保存的值就是num的地址0113F924
90d726f358ece37ac6c4ffd35aff51e8.png
0x0113F90C存储的内容为地址0113F924
  • 指针变量 pp 指向 指针 p,指针 pp 内存值为 指针 p 的地址:0113F90C,形成了只想指针的指针。
eae8fedc4349296fa4b4a984a8d7bdf5.png
指针pp为指向指针p的指针

定义指针变量

C语言中,定义变量时,在变量名 前 写一个 * 星号,这个变量就变成了对应变量类型的指针变量。必要时要加( ) 来避免优先级的问题。

引申:C语言中,定义变量时,在定义的最前面写上typedef ,那么这个变量名就成了一种类型,即这个类型的同义词。

int a ; //int类型变量 a
int *a ; //int* 变量a
int arr[3]; //arr是包含3个int元素的数组
int (* arr )[3]; //arr是一个指向包含3个int元素的数组的指针变量

int* p_int; //指向int类型变量的指针 
double* p_double; //指向idouble类型变量的指针 
struct Student *p_struct; //结构体类型的指针
int(*p_func)(int,int); //指向返回类型为int,有2个int形参的函数的指针 
int(*p_arr)[3]; //指向含有3个int元素的数组的指针 
int** p_pointer; //指向 一个整形变量指针的指针

取地址

既然有了指针变量,那就得让他保存其它变量的地址,使用& 运算符取得一个变量的地址。

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

int main(void)
{
    int num = 97;
    float score = 10.00F;
    int arr[3] = {1,2,3};

    int* p_num = #
    float* p_score = &score;
    int (*p_arr)[3] = &arr;           
    int (*fp_add)(int ,int )  = add;  //p_add是指向函数add的函数指针
    return 0;
}

特殊的情况,他们并不一定需要使用&取地址

  • 数组名的值就是这个数组的第一个元素的地址。
  • 函数名的值就是这个函数的地址。
  • 字符串字面值常量作为右值时,就是这个字符串对应的字符数组的名称,也就是这个字符串在内存中的地址。
int add(int a , int b){
    return a + b;
}
int main(void)
{
    int arr[3] = {1,2,3};
    int* p_first = arr;
    int (*fp_add)(int ,int )  =  add;
    const char* msg = "Hello world";
    return 0;
}

解地址

对一个指针解地址,就可以取到这个内存数据,解地址 的写法,就是在指针的前面加一个 * 号。

解指针的实质是:从指针指向的内存块中取出这个内存数据。

int main(void)
{
    int age = 19;
    int*p_age = &age;
    *p_age  = 20;  //通过指针修改指向的内存数据

    printf("age = %d",*p_age);   //通过指针读取指向的内存数据
    printf("age = %d",age);

    return 0;
}

空指针

空指针在概念上不同于未初始化的指针。空指针可以确保不指向任何对象或函数;而未初始化的指针则可能指向任何地方。空指针不是野指针。

在C语言中,我们让指针变量赋值为NULL表示一个空指针,而C语言中,NULL实质是 ((void*)0) ,  在C++中,NULL实质是0。

#ifdef __cplusplus
     #define NULL    0
#else    
     #define NULL    ((void *)0)
#endif

void*类型指针

void是一种特殊的指针类型,可以用来存放任意对象的地址。一个void指针存放着一个地址,这一点和其他指针类似。不同的是,我们对它到底储存的是什么对象的地址并不了解。

double a=2.3;
int b=5;
void *p=&a;
cout<
p=&b;
cout<
//cout<

由于void是空类型,只保存了指针的值,而丢失了类型信息,我们不知道他指向的数据是什么类型的,只指定这个数据在内存中的起始地址,如果想要完整的提取指向的数据,程序员就必须对这个指针做出正确的类型转换,然后再解指针。

数组和指针

  • 同类型指针变量可以相互赋值,数组不行,只能一个一个元素的赋值或拷贝
  • 数组在内存中是连续存放的,开辟一块连续的内存空间。数组是根据数组的下进行访问的。指针很灵活,它可以指向任意类型的数据。指针的类型说明了它所指向地址空间的内存。
  • 数组所占存储空间的内存:sizeof(数组名) 数组的大小:sizeof(数组名)/sizeof(数据类型),在32位平台下,无论指针的类型是什么,sizeof(指针名)都是 4 ,在 64 位平台下,无论指针的类型是什么,sizeof(指针名)都是 8 。
  • 数组名作为右值的时候,就是第一个元素的地址
int main(void)
{
    int arr[5] = {1,2,3,4,5};

    int *p_first = arr;
    printf("%d",*p_first);  //1
    return 0;
}
  • 指向数组元素的指针 支持 递增 递减 运算。p= p+1意思是,让p指向原来指向的内存块的下一个相邻的相同类型的内存块。在数组中相邻内存就是相邻下标元素。

函数与指针

函数的参数和指针

C语言中,实参传递给形参,是按值传递的,也就是说,函数中的形参是实参的拷贝份,形参和实参只是在值上面一样,而不是同一个内存数据对象。这就意味着:这种数据传递是单向的,即从调用者传递给被调函数,而被调函数无法修改传递的参数达到回传的效果。

void change(int a)
{
    a++;      //在函数中改变的只是这个函数的局部变量a,而随着函数执行结束,a被销毁。age还是原来的age,纹丝不动。
}
int main(void)
{
    int age = 60;
    change(age);
    printf("age = %d",age);   // age = 60
    return 0;
}

有时候我们可以使用函数的返回值来回传数据,在简单的情况下是可以的,但是如果返回值有其它用途(例如返回函数的执行状态量),或者要回传的数据不止一个,返回值就解决不了了。

传递变量的指针可以轻松解决上述问题。

void change(int* pa)
{
    (*pa)++;   //因为传递的是age的地址,因此pa指向内存数据age。当在函数中对指针pa解地址时,
               //会直接去内存中找到age这个数据,然后把它增1。
}
int main(void)
{
    int age = 160;
    change(&age);
    printf("age = %d",age);   // age = 61
    return 0;
}

比如指针的一个常见的使用例子:

#include 
#include 
#include 

void swap(int *,int *);
int main()
{
    int a=5,b=10;
    printf("a=%d,b=%d\n",a,b);
    swap(&a,&b);
    printf("a=%d,b=%d\n",a,b);
    return 0;
}
void swap(int *pa,int *pb)
{
    int t=*pa;*pa=*pb;*pb=t;
}

在以上的例子中,swap函数的两个形参pa和pb可以接收两个整型变量的地址,并通过间接访问的方式修改了它指向变量的值。在main函数中调用swap时,提供的实参分别为&a,&b,这样就实现了pa=&a,pb=&b的赋值过程,这样在swap函数中就通过*pa修改了 a 的值,通过*pb修改了 b 的值。因此,如果需要在被调函数中修改主调函数中变量的值,就需要经过以下几个步骤:

  • 定义函数的形参必须为指针类型,以接收主调函数中传来的变量的地址;
  • 调用函数时实参为变量的地址;
  • 在被调函数中使用*间接访问形参指向的内存空间,实现修改主调函数中变量值的功能。

指针作为函数的形参的另一个典型应用是当函数有多个返回值的情形。比如,需要在一个函数中统计一个数组的最大值、最小值和平均值。当然你可以编写三个函数分别完成统计三个值的功能。但比较啰嗦,如:

int GetMax(int a[],int n)
{
    int max=a[0],i;
    for(i=1;i    {
        if(max    }
    return max;
}
int GetMin(int a[],int n)
{
    int min=a[0],i;
    for(i=1;i    {
        if(min>a[i]) min=a[i];
    }
    return min;
}
double GetAvg(int a[],int n)
{
    double avg=0;
    int i;
    for(i=0;i    {
        avg+=a[i];
    }
    return avg/n;
}

其实我们完全可以在一个函数中完成这个功能,由于函数只能有一个返回值,可以返回平均值,最大值和最小值可以通过指针类型的形参来进行实现:

double Stat(int a[],int n,int *pmax,int *pmin)
{
    double avg=a[0];
    int i;
    *pmax=*pmin=a[0];
    for(i=1;i    {
        avg+=a[i];
        if(*pmax        if(*pmin>a[i]) *pmin=a[i];
    }
    return avg/n;
}

函数的指针

一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址。我们可以把函数的这个首地址赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。

函数指针的定义形式为:

returnType (*pointerName)(param list);

returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。

用指针来实现对函数的调用:

#include 
//返回两个数中较大的一个
int max(int a, int b)
{
    return a>b ? a : b;
}
int main()
{
    int x, y, maxval;
    //定义函数指针
    int (*pmax)(int, int) = max;  //也可以写作int (*pmax)(int a, int b)
    printf("Input two numbers:");
    scanf("%d %d", &x, &y);
    maxval = (*pmax)(x, y);
    printf("Max value: %d\n", maxval);
    return 0;
}

结构体和指针

结构体指针有特殊的语法: -> 符号

如果p是一个结构体指针,则可以使用 p ->【成员】 的方法访问结构体的成员

typedef struct
{
    char name[31];
    int age;
    float score;
}Student;

int main(void)
{
    Student stu = {"Bob" , 19, 98.0};
    Student*ps = &stu;

    ps->age = 20;
    ps->score = 99.0;
    printf("name:%s age:%d
",ps->name,ps->age);
    return 0;
}

const 和 指针

  • 指向常量的指针,值不能改变,指向可改变
  • 常指针值能改变,指向不可改变
  • 指向常量的常指针,都不能改变
#include 
 
int main()
{
  // 1 可改变指针
  const int a = 10;
  int *p = &a;
  *p = 1000;
  printf("*p = %d\n", *p);
 
  // 2 可改变指针
  const b = 10;
  int *pb = &b;
  pb = p;
  printf("*pb = %d\n", *pb);
 
  // 3
  const c = 10;
  int * const pc = &c;
  *pc = 1000;
  //pc = pb;不能改变
 
  //4
  const d = 10;
  const * int const pd = &d;
  //*pd = 1000; 不能改变
 
 
  printf("\n");
  return 0;
}

深拷贝和浅拷贝

如果2个程序单元(例如2个函数)是通过拷贝 他们所共享的数据的 指针来工作的,这就是浅拷贝,因为真正要访问的数据并没有被拷贝。如果被访问的数据被拷贝了,在每个单元中都有自己的一份,对目标数据的操作相互 不受影响,则叫做深拷贝。


#include 
using namespace std;

class CopyDemo
{
public:
  CopyDemo(int pa,char *cstr)  //构造函数,两个参数
  {
     this->a = pa;
     this->str = new char[1024]; //指针数组,动态的用new在堆上分配存储空间
     strcpy(this->str,cstr);    //拷贝过来
  }

//没写,C++会自动帮忙写一个复制构造函数,浅拷贝只复制指针,如下注释部分
  //CopyDemo(CopyDemo& obj)  
  //{
  //   this->a = obj.a;
  //  this->str = obj.str; //这里是浅复制会出问题,要深复制
  //}

  CopyDemo(CopyDemo& obj)  //一般数据成员有指针要自己写复制构造函数,如下
  {
     this->a = obj.a;
    // this->str = obj.str; //这里是浅复制会出问题,要深复制
     this->str = new char[1024];//应该这样写
     if(str != 0)
        strcpy(this->str,obj.str); //如果成功,把内容复制过来
  }

  ~CopyDemo()  //析构函数
  {
     delete str;
  }

public:
     int a;  //定义一个整型的数据成员
     char *str; //字符串指针
};

int main()
{
  CopyDemo A(100,"hello!!!");

  CopyDemo B = A;  //复制构造函数,把A的10和hello!!!复制给B
  cout <<"A:"<"," <  //输出A:100,hello!!!
  cout <<"B:"<"," <  //输出B:100,hello!!!

  //修改后,发现A,B都被改变,原因就是浅复制,A,B指针指向同一地方,修改后都改变
  B.a = 80;
  B.str[0] = 'k';

  cout <<"A:"<"," <  //输出A:100,kello!!!
  cout <<"B:"<"," <  //输出B:80,kello!!!

  return 0;
}

根据上面实例可以看到,浅复制仅复制对象本身(其中包括是指针的成员),这样不同被复制对象的成员中的对应非空指针会指向同一对象,被成员指针引用的对象成为共享的,无法直接通过指针成员安全地删除(因为若直接删除,另外对象中的指针就会无效,形成所谓的野指针,而访问无效指针是危险的;

除非这些指针有引用计数或者其它手段确保被指对象的所有权);而深复制在浅复制的基础上,连同指针指向的对象也一起复制,代价比较高,但是相对容易管理。

参考资料

  1.    C Primer Plus(第五版)中文版
  2. https://www.cnblogs.com/lulipro/p/7460206.html

- EOF -

bf2b9cc01ddad8df064a8cada47f7aa5.png

推荐阅读  点击标题可跳转

1、C语言为何不会过时?你需要掌握多少种语言?

2、48 岁的 C 语言,你知道它背后的历史吗?

3、一文读懂 C 语言与 C++ 动态内存

看完本文有帮助?请分享给更多人

关注「CPP开发者」加星标,提升C/C++技能

05a76bb77d109c69ba39b4640dc7be58.png

好文章,我在看❤️

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

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

相关文章

idea修改代码后不重启项目_使用DevTool实现SpringBoot项目热部署

前言最近在开发的时候&#xff0c;每次改动代码都需要启动项目&#xff0c;因为有的时候改动的服务比较多&#xff0c;所以重启的次数也就比较多了&#xff0c;想着每次重启等待也挺麻烦的&#xff0c;就打算使用DevTools工具实现项目的热部署热部署是什么大家都知道在项目开发…

c++ 单例模式_Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比

redis作为一种高效的缓存框架&#xff0c;使用是非常广泛的&#xff0c;在数据存储上&#xff0c;在运行时其将数据存储在内存中&#xff0c;以实现数据的高效读写&#xff0c;并且根据定制的持久化规则不同&#xff0c;其会不定期的将数据持久化到硬盘中。另外相较于其他的NoS…

jenkins 插件目录_10 个 Jenkins 实战经验,助你轻松上手持续集成

众所周知&#xff0c;持续构建与发布是我们日常工作中要面对的的一个重要环节&#xff0c;目前很多公司都采用 Jenkins 来搭建符合需求的 CI/CD 流程&#xff0c;作为一个持续集成的开源工具&#xff0c;它以安装启动方便&#xff0c;配置简单&#xff0c;上手容易的特点&#…

jdbc 批量insert_JDBC相关知识解答

1. JDBC_PreparedStatement插入大量数据_批处理插入_效率比较(1) jdbc新增大量数据时, 如何处理能提高效率?答&#xff1a;使用批处理提高效率(2) 什么是批处理? JDBC如何进行批处理?答&#xff1a;批处理&#xff1a;在与数据库的一次连接中&#xff0c;批量的执行条 SQL 语…

python 实现显著性检测_强!汽车车道视频检测:python+OpenCV为主实现

1 说明&#xff1a;1.1 完整版&#xff1a;汽车车道动态视频检测讲解和注释版代码&#xff0c;小白秒懂。1.2 pythonOpenCVmoviepynumpy为主的技术要点。1.3 代码来源&#xff1a;https://github.com/linghugoogle/CarND-Advanced-Lane-Lines #虽然感觉也是fork别人的&#xff…

如何学习c语言 零基础20天学会C语言

C语言开发 学习C语言不是一朝一夕的事情&#xff0c;但也不需要花费十年时间才能精通。如何以最小的代价学习并精通C语言是本文的主题。请注意&#xff0c;即使是“最小的代价”&#xff0c;也绝不是什么捷径&#xff0c;而是以最短的时间取得最多的收获&#xff0c;同时也意味…

学习C/C++的简单方法

如何学习C呢。C和C是很多专业的必修课&#xff0c;尤其对计算机专业来说&#xff0c;更是重中之重。C语言是早期发展的高级语言&#xff0c;具备执行速度快&#xff0c;语法优美等特点。是底层高效率系统的首选开发语言。今天就和大家分享一下怎么学好C/C语言吧 _ 怎么学好C、…

python数据预处理代码_Python中数据预处理(代码)

本篇文章给大家带来的内容是关于Python中数据预处理&#xff08;代码&#xff09;&#xff0c;有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对你有所帮助。1、导入标准库import numpy as np import matplotlib.pyplot as plt import pandas as pd 2、…

零基础想学好C语言编程,首先要掌握的是正确的学习思路!

如果新手要学习编程&#xff0c;一些前辈都会建议从Python、PHP、Java开始学。 不过&#xff0c;有些程序员是直接从C语言强势入门编程的。 那么&#xff0c;如何学习C语言呢?下面提供4种入门C语言的方法&#xff1a; 0、刷题 绝大多数的程序员学编程的时候&#xff0c;还…

C/C++初学者快速提升?

如今&#xff0c;软件开发行业继续向前大步迈进。信息技术越来越吃香&#xff0c;越来越多人学习学习c语言&#xff0c;那么如何系统有效的学习C语言?下面分享给大家的有效学习语言的方法&#xff0c;希望可以帮到你! 一、了解大纲&#xff0c;通览教材 想学好C语言最重要的一…

pytorch 矩阵相乘_深度学习 — — PyTorch入门(三)

点击关注我哦autograd和动态计算图可以说是pytorch中非常核心的部分&#xff0c;我们在之前的文章中提到&#xff1a;autograd其实就是反向求偏导的过程&#xff0c;而在求偏导的过程中&#xff0c;链式求导法则和雅克比矩阵是其实现的数学基础&#xff1b;Tensor构成的动态计算…

codeblocks如何让输出结果 空格_简单讲讲如何实现两个正整数相加,然后输出这个结果...

首先吧&#xff0c;两个整数123 456&#xff0c;相加得到579&#xff0c;我们就得输出579&#xff0c;这个很容易操作&#xff0c;但是如果是&#xff1a;1212161596156198115645646886148461554 2671232162176217624372497590415915915029125 呢&#xff1f;long ? long lo…

C语言和其他高级语言的最大的区别是什么?

提到C语言&#xff0c;我们知道C语言和其他高级语言的最大的区别就是C语言是要操作内存的&#xff01; 我们需要知道——变量&#xff0c;其实是内存地址的一个抽像名字罢了。在静态编译的程序中&#xff0c;所有的变量名都会在编译时被转成内存地址。机器是不知道我们取的名字…

零基础学C语言必备书籍,抖音编程达人推荐(进群交流学习互动)

C语言从入门到进阶的书籍推荐。 【基础】 这本谭浩强写的【C语言程序设计】可谓是广大人事的入门书籍。我曾经用的教材就是这本&#xff0c;里面大概涵盖了 C语言 语法的 80% 。一个很适合自学的入门书。 【c prime puls】 是 C语言 最经典的入门书籍&#xff0c;极力推荐。每…

网站如何进行渠道跟踪_网站如何进行搜索引擎优化?

这是一个很一般的平台标题&#xff0c;没有任何吸引力&#xff0c;但是它真的可以被一个很好的基层站长估计的很少&#xff0c;我问一个做了多年基层站长的朋友&#xff0c;我说如何做好搜索引擎优化的SEO&#xff0c;他给我的答案很难&#xff0c;答案太大了&#xff0c;所以我…

什么是编程语言,大神教你为什么要学C语言?

首先来说说编程语言这个概念。 编程&#xff0c;其实就是让计算机听懂自己的话&#xff0c;让计算机帮自己想干的事情。编程语言&#xff0c;就是让你能够和计算机进行交流的一种语言。说白了就是让你的软件按你的命令干活。 打比方说&#xff0c;我们经常在僵尸片里面看到&a…

xshell vim 不能粘贴_linux基础知识:vim(vi)的知识

### vim三种模式命令行模式&#xff1a;在该模式下不能对文本进行- 直接编辑&#xff0c;可以输入一些操作(删除行&#xff0c;复制行&#xff0c;移动光标&#xff0c;粘贴)【打开之后默认进入的模式】编辑模式&#xff1a;在该模式下可以对文件内容进行编辑末行模式&#xff…

新手如何学习C语言/C++,教你一年时间是拿到年薪50万

最近会有一些初中高中大学的同学问&#xff0c;C语言C不知道怎么学习不会写代码怎么办&#xff1f;大致上都是一些类似的问题吧&#xff0c;回想一下自己走过的路&#xff0c;反复的了很久思考然后写了这篇文章&#xff0c;希望可以对一些迷惘新手小白程序员同学一丝帮助&#…

mac adb 找不到设备_win/Mac办公软件下载找不到资源?试试这三个强大的神器

大家好&#xff0c;我们在办公时&#xff0c;office、wps等办公软件是我们必须用到的&#xff0c;还有一些专业软件&#xff1a;CAD、PS、PROE、UG、SolidWorks、keyshot、VRay、3DsMax、Labview、Maya、AE、AI、ANSYS等也是各行各业的专业人员工作时必不可少的&#xff0c;但是…

C语言入门经验:零基础如何学习C语言?

工作中&#xff0c;接触过很多想到学习c语言而又没有一点计算机基础的人。经常有人问”我没有一点基础&#xff0c;该怎么入门c语言啊”。看过很多初学者久久摸不到门路&#xff0c;每到这个时候&#xff0c;脑海中总会浮现一个问题&#xff1a;学习c语言真的就那么难吗? 不难…