关于Linux C的初级编程,在麦子学院上对应于5小节的课程:

  1. c语言语法概述
  2. c语言内存操作
  3. c语言函数使用
  4. linux 操作系统基础
  5. GNU工具简介

因为内容有点多,本篇文章主要总结了前3节的C语言基础部分。
后2节的linux部分请看下一篇文章:https://blog.csdn.net/QiHsMing/article/details/85961964

c语言语法概述

GCC的使用及其常用选项介绍

GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语言编译器的意思了,而是变成了 GNU Compiler Collection

GCC的常用命令:
详细教程请查看:https://blog.csdn.net/typename/article/details/8170213

命令 描述
1 gcc mian.c 指定输出可执行文件的名字执行完上面这句命令,会在当前目录下输出一个名为a.out的可执行文件。
2 gcc -o main main.c 使用 -o选项可以指定输出的可执行文件名称, -->预处理+编译 +汇编 +链接
3 gcc -Wall main.c -o main 让所有编译警告都显示出来
4 gcc -E main.c > main.i 只输出预编译结果
5 gcc -S main.c > main.s 输出汇编代码 -->预处理+编译
6 gcc -C main.c 输出编译后的代码,生成.maino文件 -->预处理+编译 +汇编
7 gcc -save-temps main.c 输出所有的中间代码(a.out main.c main.i main.o main.s)
8 gcc -Wall main.c -o main -lpthread 链接共享库(动态链接库)指定编译选项 -lxxx,比如使用多线程需要链接 -lpthread共享库
9 gcc -Wall -v main.c -o main 打印输出有个执行过程的信息 使用-V选项
10 gcc -Wall -ansi main.c -o main 指定编译选项-ansi,支持ISO C89 programs.
11 gcc -Wall -funsigned-char main.c -o main 指定编译选项 -funsigned-char选项将char类型解释为unsigned char类型
12 gcc -Wall -fsigned-char main.c -o main 指定编译选项 -fsigned-char选项将unsigned char类型解释为 char类型
13 gcc -Wall -D MY_MACRO main.c -o main 指定-D选项 开启编译时的宏
14 gcc -Wall -Werror main.c -o main 将编译警告转换成错误
15 gcc main.c @opt_file 通过文件指定编译选项,指定@编译选项

c语言常见错误

c语言常见错误有以下几类:

  • 预处理错误:一般是找不到头文件。
  • 编译错误:语法错误,内存错误。
  • 链接错误:原材料不够,原材料多了。

预处理

关键字 用法 意义
include #include 头文件 包含头文件
define #define 宏名 宏体 相当于常量,不进行语法检查
ifdef else endif #ifdef 宏名 #else 宏体 #endif 常与gcc -D同时使用

条件编译的使用代码:

#include <stdio.h>
int main()
{
ifdef ABCprintf(“====%s====”,__FILE__);
#endifprintf("Hello World !");return 0;
}

编译时,使用gcc -D命令:

gcc -DABC -o test 003.c

预定义宏

__FUNCTION__ //函数名
__LINE__            //行号
__FILE__            //文件名

预定义宏的使用代码:

#include<stdio.h>
int fun()
{int a;printf(" the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);return 0;
}
int main()
{fun();return 0;
}

宏展开下的#与##的使用

#  字符串化
##   宏序列化

格式:

#define   ABC(x)     #x
#define   ABC(x)    day##x

#的使用代码:

 #include <stdio.h>#define ABC(x)   #xint main(){printf(ABC(ab\n));        //相当于printf("ab\n")   输出ab\nreturn 0; }

##的使用代码:

 #include <stdio.h>#define DAY(x)   day##xint main(){int day1 = 10;int day2 = 20;printf("the day is %d\n",DAY(1));     //输出10return 0; }

C语言常用关键字及运算符操作

关键字
关键字概念:编译器预先定义了一定意义的字符串。

sizeof:编译器给我们查看内存空间容量的一个工具。
return:定义函数的返回值。

数据类型关键字:限制内存大小的关键字。

常用的数据类型有

数据类型 位宽
char 8bit
short 16bit
int 32bit
long 64bit
float 23bit
double 64bit

自定义数据类型:struct,union,enum,typedef。
struct结构体:元素之间的和

struct   结构体名{
成员1
成员2
...
}

union联合体:元素之间的累积,首地址共用。

union结构体名{
成员1
成员2
...
}

enum枚举:被命名的整形常量的集合。

enum 枚举名 { 常量列表}例:enum week{Mondey = 0, Tuesday = 1, Webnesday = 2, Thursday, Friday, Saturday,Sunday};

typedef:数据类型的别名。

逻辑结构
逻辑结构包括:

a. 判断语句:if-else 、switch-case
b. 循环语句:do-while、for
c. 中断:continue、break、goto

类型修饰符:对内存资源存放位置的限定,资源属性中位置的限定。 有:register,static_const,volatile。

运算符

a.算术操作运算:+、-、、/、%、mod。
b.逻辑运算:&&、||、>、>=、<、<=、!、?:
c.位运算:~、&、|、^、<<、>>
赋值运算:=、+=、-=、&=
内存访问符:()、[]、{}、->、&、

C语言内存空间的使用

指针

指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。

指针变量 的大小由它的数据类型决定。指针的数据类型不同,可以导致取地址的内容不同。

例:

#include <stdio.h>
int main()
{int a = 0x12345678;int *p1;char *p2;p1 = &a;p2 = &a;printf ("the p1 is %x\n",*p1);printf ("the p2 is %x\n",*p2);
}

编译后,运算结果:

指针+修饰符

修饰指针的修饰符有:const、volatile、typedef。
1)const :常量,只读。

写法1:const char *p; 通常修饰常用的字符串
写法2:char * const P; 通常修饰硬件资源
写法3:const char *const p;通常修饰地址不可变且内容不可变的ROM

例1:指针指向的内容被非法访问了

#include <stdio.h>int main()
{char *p = "Hello World !";  printf("the one is %x\n",*p);*p = 'a';printf("the %x\n",p);
}

运行结果:

例2:指针操作数组

#include <stdio.h>int main()
{char *p = "Hello World !";char buff[] = {"Hello World !"};char *p1 = buff;printf("the one is %x\n",*p1);*p1 = 'a';printf("the %s\n",p1);
}

运行结果:

例3:const 修饰的指针变量不能改变

#include <stdio.h>int main()
{const char *p = "Hello World !";char buff[] = {"Hello World !"};char *p1 = buff;printf("the one is %x\n",*p1);*p = 'a';printf("the %s\n",p1);
}

运行结果:

volatile:防止优化指向内存地址
typedef:为指针变量起别名

指针+运算符

在指针中的运算符有:(1)加减运算符 (2)逻辑运算符

(1)加减运算符:指针的加法减法运算,实际上加的是一个单位,单位的大小可以使用sizeof(p[0]),运算符有:++ 、–。

例:指针+运算符加减

#include <stdio.h>int main()
{int a = 0x123456789;int b = 0x99991199;int *p1 = &b;char *p2 = (char *)&b;printf("the p1+1 is %x,%x,%x\n",*(p1+1),p1[1],*p1+1);printf("the p2+1 is %x\n",p2[1]);
}

运行结果:

(2)逻辑运算符:运算符有:>=、<=、==、!=

多级指针

多级指针:指向存放地址的地址空间。
例:

#include <stdio.h>int main(int argc,char **argv)
{int i = 0;while(argv[i] != NULL){printf("the argv[%x] is %s\n",i,argv[i]);i++;}return 0;
}

运行结果:

数组

数组:内存分配的一种形式。

数组空间的初始化
一般原则,数组空间的赋值是按照标签逐一处理,但这样赋值的工作量比较大;让编译器进行自动处理,就是空间初始化。

数组初始化方式:

方式一: char buf[] =“abc”;
方式二:char buf[10] = “abc”;

指针数组:数组中存放的是一组指针地址

数组名的指针保存

例1:定义一个指针,指向int a[10]的首地址
int a[10];
int *p a;

例2:定义一个指针,指向int b[5][6]的首地址
int b[5][6];
int (*p)[5]

结构体字节对齐

合理的内存对齐可以提高访问效率。为使CPU能够对数据进行快速访问,数据的起始地址应具有“对齐”特性。比如4字节数据的起始地址应位于4字节边界上,即起始地址能够被4整除。

关于结构体字节对齐具体参考:https://www.cnblogs.com/clover-toeic/p/3853132.html

例:

#include <stdio.h>struct csi{char  a;short b;int c;
};struct cis{char a;int c;short b;
};int main()
{struct csi buf1;struct cis buf2;   printf("csi : cis is %lu:%lu\n",sizeof(buf1),sizeof(buf2));return 0;
}

运行结果:

内存分布

内存分布:https://www.cnblogs.com/yanhewu/p/8360541.html
https://blog.csdn.net/xyh930929/article/details/79496659

典型的C语言程序内存表示分区共有5个部分:

① 正文段 Text segment
② 已初始化数据段(数据段)Initialized data segment
③ 未初始化数据段(bss)Uninitialized data segment
④ 堆 Stack
⑤ 栈 Heap

内存区域 存放 作用
text 段 字符串常量和函数体的二进制代码 通常可共享,只读
data段 已初始化全局变量、静态变量 通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
bss段 未初始化全局变量、静态变量 通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS段属于静态内存分配。(注意:即使是赋值为0也是未初始化!)
Stack malloc内存分配 用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。
Heap 局部变量、在函数调用时的形参和返回值 为最近被调用的函数分配自动变量和临时变量的存储空间

具体分布图

C语言函数的使用

函数的概述:一堆代码的集合,具有复用性。
函数的三要素:①函数名②参数③返回值

1. 形参与实参
在代码中,函数有两种形式:调用者和被调者。

调用者:

  函数名(要传递的数据)         //实参

被调者:

函数名(接收的数据)                //形参
{函数的具体实现
}

函数实参形参拷贝举例:

运行结果:

2. 值传递、地址传递和连续空间传递

传递:实参和形参的数据传递

① 值传递:将实参的数据copy给形参,不改变实参的数据,函数调用完后,形参数据销毁。

值传递的作用:上层调用者保护自己的空间值不被修改。

值传递示例:

运行结果:

② 地址传递:将实参的地址传给形参。形参的数据被修改的同时,实参的数据也会被修改。

地址传递的作用:上层调用者,让下层函数修改自己的空间值。
注意:static修饰的变量进行传参的,都是地址传递。
地址传递示例:

运行结果:

③连续空间传递:包括数组空间传递和结构体空间传递,连续空间的传递大都是地址传递。

数组空间传递:都是地址传递

int abc[10];         //定义实参:
fun(abc);形参:
void fun(int *p)                等价于         void fun(int p[10])

结构体空间传递:

struct abc {int a,int b,int c};              //定义
struct abc buf;                             //别名实参:
fun(buf);                                   //值传递
fun(&buf);                                  //地址传递形参:
void fun(struct abc a)                      //值传递
void fun(struct abc *a)                     //地址传递

面试常见的知识点:

1)宏定义,可以是表达式,编译过程中已经计算了表达式

#define SECOND_OF_YEAR (365*24*3600)UL

2)数据声明

用变量a给出下面的定义

①一个整形数
int a;
②一个指向整型数的指针
int *a
③一个指向指针的指针,它指向的指针是指向一个整型数
int **a
④一个有10个整型数的数组
int a[10]
⑤一个有10个指针的数组,该指针是指向一个整型数的
int *a[10]
⑥一个指向有10个整型数数组的指针
int (*a)[10]
⑦一个指向函数的指针,该函数有一个整形参数并返回一个整形数
int * fun(int a);
⑧一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整形数
int (*fun[10])(int a)
3)修饰符:

嵌入式系统开发-麦子学院(3)——Linux C初级编程1相关推荐

  1. 嵌入式系统开发-麦子学院(4)——Linux C初级编程2

    上篇文章讲到了Linux C初级编程的C语言基础部分:https://blog.csdn.net/QiHsMing/article/details/84947781 下面接着Linux C初级编程的L ...

  2. 嵌入式系统开发-麦子学院(12)——ARM Cortex A8 硬件基础(2)

    S5PV210启动原理 ARM启动顺序 BL0(IROM)的作用 初始化系统时钟,设置看门狗,初始化栈和堆 加载BL1 BL1的作用 初始化RAM,关闭Cache,设置栈 加载BL2 BL2的作用 初 ...

  3. 嵌入式系统开发笔记2:Linux的主流发行版本

    本系列文章将向大家介绍嵌入式系统开发的各方面知识. 本文将向大家介绍Linux的主流发行版本. 本文为转载文章,原文网址:Linux各个发行版本对比与简介 首先我们要能够清晰的区分Linux系统内核与 ...

  4. 从零开始的嵌入式系统开发学习Day3(linux C)

    目录 一.输入输出函数 1.1 getchar()/putchar() 1.1.1 getchar() 1.1.2 putchar() 1.2 get()/puts() 1.2.1 gets() 1. ...

  5. 嵌入式系统开发笔记0_0:目录

    本系列文章将向大家介绍嵌入式系统开发的各方面知识. 本系列文章所介绍的知识和内容,除电路图设计外,其它均采用开源系统,所以你不会在这个系列文章中看到Keil.IAR等软件. 本系列文章涉及C.C++. ...

  6. 嵌入式系统开发学习步骤(Linux高级编程学习顺序)

    2019独角兽企业重金招聘Python工程师标准>>> 嵌入式系统开发学习步骤(Linux高级编程学习顺序) 1.Linux 基础 安装Linux操作系统 Linux文件系统 Lin ...

  7. LINUX嵌入式系统开发平台选择

    1 嵌入式系统与Linux 按照电气工程师协会的一个定义:嵌入式系统是用来控制或监视机器.装置或工厂等的大规模系统的设备.具体说来,它是电脑软件和硬件的综合体:是以应用为中心,以计算机技术为基础,软硬 ...

  8. 嵌入式系统开发学习如何起步、如何深入?(转)

    学习有捷径吗?俺认为是有的,正确的道路就是捷径. 就好象是爬山,如果有导游图,那就能找到一条最正确的路线:如果没有导游图,自己瞎琢磨,东问西问,也未必能找到最佳的路线. 有时候回首前尘,会谓叹,要是当 ...

  9. 嵌入式系统开发怎样快速度入门

    http://wenda.tianya.cn/wenda/thread?tid=392a249d9d6856c5 实践当然是最锻炼人的方式,但是我想在校生很少有这样的机会,别说本科生,硕士生也未必有条 ...

  10. labview嵌入c代码_LabVIEW与myRIO嵌入式系统开发入门

    一.概述 NI myRIO是NI公司推出的一款嵌入式系统开发平台,内嵌Xilinx Zynq芯片,可以利用双核ARM Cortex-A9的实时性能以及Xilinx FPGA可定制化I/O进行嵌入式系统 ...

最新文章

  1. 关于java代码生成器---上篇之原理
  2. 28-Interview-面试
  3. 成功解决你没有权限访问,请与网络管理员联系图文教程
  4. 基于直方图的图像增强算法(HE、CLAHE、Retinex)
  5. Python:安装dlib库
  6. Mac下给sublime text3配置Nodejs
  7. 博弈论 从懵逼到入门 详解
  8. 软考项目管理师考试随笔
  9. Typora自动生成标题编号(包含从二级标题开始的)
  10. dedecms如何制作中英文切换的网站?
  11. 漂浮广告代码、漂浮代码分析(讲解)
  12. Win10上注册OCX文件
  13. win7网络里计算机登录失败,Win7访问网上邻居提示“登陆失败”原因及解决方法...
  14. [转]页面回传与js调用服务器端事件
  15. Spring boot 项目(十二)——实现电脑网页微信扫码自动授权
  16. C|倒三角(trangle)
  17. C51流水灯由开关控制自下而上自上而下的实验
  18. c语言中%p和%x的意思
  19. 面向高维稀疏数据场景,阿里妈妈宣布开源XDL深度学习框架
  20. c聊天室系统asp ajax,利用AJAX和ASP.NET实现简单聊天室

热门文章

  1. android打开sd卡文件,从Android中的SD卡读取特定文件
  2. WindowsLiveWriter安装步骤
  3. Aras Innovator: 扩展Part类型,管理更多的物体类型
  4. 2011年下半年11月份系统架构设计师上午试题答案之二
  5. 预约洗车/美容/维修/家政/保养/上门洗车预约小程序源码及管理系统
  6. 1362:家庭问题(family)
  7. 300英雄11月服务器维护,300英雄11月7日更新了什么?300英雄11月7日更新内容一览...
  8. 巩固大一,大二知识 练习计划
  9. 初生牛犊不怕虎 —— 独自背井离乡
  10. 访问项目,页面打开太慢解决方式