C语言高级Day01LinuxC环境、指针

一、Linux C环境

(一)GCC编译工具

  1. GCC编译工具:是一个将C源码工程编译为可执行程序的一个工具。
  2. GCC编译流程:
  • 预处理:是将c文件中的头文件、宏定义等进行替换。预处理不会报错。

//将C文件进行预处理,生成.i后缀文件

gcc -E C文件名

  • 编译(分析器):是将预处理过后的文件(.i后缀文件)编译为汇编文件(.s后缀文件);会进行语法检测,会报语法错误。

//将.i后缀文件编译成一个汇编文件(.s后缀文件)

gcc -S 预处理文件名

  • 汇编(汇编器):是将汇编文件(.s后缀文件)扁你一为二进制目标文件(.o后缀文件)

//将.s文件扁你一为二进制目标文件(.o后缀文件)

gcc -c 文件名

//或者使用as汇编器

as

  • 链接(链接器):将多个目标文件或依赖库进行链接,生成可执行目标文件。报链接错误。

//

gcc 二进制目标文件(.o后缀文件)-o 可执行文件名

3.编译出错:不能生成可执行程序。

  • C语法错误
  • 头文件错误
  • 档案库错误(链接错误)
  • 未定义引用错误
  1. 逻辑错误:编译通过,可生成逻辑程序。
  • 段错误:非法操作内存,数组溢出,操作越界,指针的非法访问……
  • 输入输出格式错误

(二)GDB调试

  1. 编译时添加-g选项,附加调试信息。
  2. 进入调试模式:gdb ./可执行文件名
  3. GDB使用方法:
  • (gdb) l 行号:查看源码对应行位置
  • (gdb) b 行号:设置断点,程序运行到该位置时停止。
    • 查看断点情况:(gdb) info b
    • 删除断点:del 断点数字
  • (gdb) r:运行代码
    • (gdb) n:运行一行
    • (gdb) s:若这一行时函数调用
    • (gdb) c:恢复程序运行
  • 栈回溯命令:backtrace 专门处理段错误问题
  • (gdb) quit:退出gdb调试工具。
  1. 逻辑错误的调试:常用打印法调试。

二、存储类型

(一)五类存储类型

  1. 自动(auto):
  • 全局变量:全局区/静态区,全局的作用域,有外部链接,有全局生命周期。
  • 局部变量:栈区,局部变量的作用域,空链接,有局部生命周期。
  1. 寄存器(register):
  • 不是强制的,是一种事情,该类型变量不能取地址操作,一般使用较少。
  1. 外部变量(extern):
  • 修饰全局变量,表示这个变量不是本文件中定义的,是引入其他文件的。
  • 全局的作用域:由外部链接,有全局生命周期。
  1. 静态变量(static):
  • 修饰全局变量,作用域受限的全局变量。作用域只能在当前文件中使用和访问,不能在其他文件访问,不能被extern。
  • static修饰函数,表示该函数只能在当前文件中被调用,不能被其他文件调用。
  • static修饰局部变量,扩展其生命周期,表示该局部变量存储位置变更为静态区。局部的作用域空链接、有全局生命周期。
  1. const:修饰变量,限制变量 访问,可读不可写。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CSu8QEbf-1655466691896)(F:\华清嵌入式\嵌入式学习\C语言\Linux基础与C高级\Linux基础\Linux基础Day04\存储类型.jpg)]

三、指针

  1. 指针:指指针变量,一个变量(有存储空间),存放的是一个内存地址;也指内存地址。
  2. C语言的灵魂:指针操作内存的工具,灵活性非常高。
  3. 指针变量的定义:
  • 定义格式:

存储类型 数据类型* 变量名 = 初始值

示例:

int *p;//野指针,指针变量中存放的是一个随机地址或无效地址

int *p = NULL;//空指针,只能进行赋值操作,取地址操作

  1. 二级整型指针:指指针类型变量,存放的是另一指针变量的地址。“int * *pp;”。
  2. 指针的赋值:本质是建立指向关系。指针变量 = 指针类型地址
  • 指针类型地址:可以通过对应类型的变量取地址操作进行得到;
  1. 指针操作:“*”运算。单目运算符,位于指针的左边,本质是访问指针指向的对象。对*p的操作等同于对其指向的对象的操作。
  2. 指针变量的存储大小:64位机:其存放地址的空间需要8字节;32位机
  • 64位机:其存放地址的空间需要8字节
  • 32位机:其存放地址的空间需要4字节
  • 与指针指向类型无关
  1. 指针的算术运算:
  • 指针与整数的运算:只能+、-运算,本质是指向关系发生移动,其移动单位不是字节,而是指向的对象。不能进行*、/、%运算。
int a;
int *p = &a;
printf("&a=%p\n",&a);
printf("p=%p\n",&p);
p += 1;//其结果是a的内存地址+1字节
printf("p=%p\n",&p);
  • 指针与指针可以进行“-”操作,其结果是一个整型,其物理意义是计算来给你个指针间相距多远,单位以对线计,但是这两个的指针的类型必须一直,且这两个指针需要指向同一段连续的内存空间。

练习:使用指针方式求一个字符串的长度

//使用指针方式求一个字符串的长度
#include <stdio.h>

int main()
{
    char str1[] = "hello world!";
    char *p = str1;
    int lenth = 0;
    while(*p++ != '\0')
    {
        lenth++;
    }
    printf("lenth = %d\n",lenth);  
    return 0;
}

  1. 指针的关系运算:两个指针间可以进行关系运算,其运算本质是判定这两个指针的位置关系,这两个指针需要在同一连续内存中,且类型一致。
  2. const修饰指针变量:
const char *str = "hello";//常量字符串指针
const char *p = "OK";//常量字符串指针
*p = 'h';//指针指向的内容不能修改
p = str;//指针指向的关系可以修改
const char * const p1 = str;//指针指向关系不能修改,指向的内容也不能修改
char * const p2 = str;//指针指向的关系不能修改,指向的内容可以修改。
  1. void关键字:
  • void修饰函数:修饰函数表示该函数没有返回值。
  • void修饰指针变量,万能指针,表示该指针暂时可以指向任意类型但是不能直接使用,*、++、<、>……使用时需强制类型转换。

四、指针与数组

(一)指针数组与二级指针

  1. 字符串指针数组:数组里面存放的是字符串的地址。
  2. 二级指针:指针指向的对象也是指针,该类指针称为二级指针。

char s1[] = “are you ok”;
char s2[] = “你好”;
char s3[] = “兽人必须死”;
char s4[] = “上海”;

//字符串数组

char *arr[5]={s1,s2,s4,s3,NULL};

//二级指针

char * * p = arr;

(二)数组指针

  1. 数组指针:数组指针指向的对象是二维数组的首元素地址。

int arr[3][4]; arr => int [4];
int (*p)[4] = arr; // 数组指针 一个指向数组首元素的 指针

练习:

char *arr[5]={“hello”,“world”,“are you ok”,“ok”,NULL}

char * *p = arr;

求表达式的值:假设每个表达式中p = arr;

*p; *p==>*arr ==>“hello”

**p; **p==>*(*arr )>*(“hello”)>‘h’

*(p+1); *(p+1)>*(arr+1)>*(“world”)==>“world”

*(*p+1); *(*p+1)>*(*arr+1)>*(“hello”+1)>*(“ello”)>‘e’

*(*(p+1)+1); *(*(p+1)+1)>*(*(arr[1])+1)>*(“world”+1)>*(“orld”)>‘o’

**p++;>**arr>*(“hello”)==>‘h’

*(*p)++;>*(“hello”)++>‘h’

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值