导图社区 麦子学院嵌入式共享
麦子学院嵌入式共享思维导图,包括:GCC的使用及其常用选项介绍、C语言常用关键字及运算符操作、C语言内存空间的使用、C语言函数的使用、常见面试题目讲解。
编辑于2022-06-25 22:52:17麦子学院嵌入式共享
作者:王海宁 QQ: 2110697186
基础阶段
Lesson2 嵌入式C语言高级
课程介绍
本套课程的定位
前导课程:掌握简单C语言的基本语法 计算机程序语言的学习思路? 基本程序设计思想 + 语言工具的特性 基本程序设计思想: 数据类型、运算符、条件分支、循环设计 面向对象的设计 C语言工具的特性: 比如操作底层,尤其是内存地址的寻址及操作,指针的使用 掌握C语言的设计思路,比普通的语法要重要的多 万变不离其宗,掌握C语言的核心规律。
本套课程的想法
不是教程,是一种嵌入式C语言思想和设计的交流 什么时候用? 怎么用? 为什么要这样设计?
推荐教程
C语言深度解剖(第2版)解开程序员面试笔试的秘密 C 专家编程 程序员面试宝典(第4版) C 和指针
偏重嵌入式方向的使用
嵌入式课程的特点 ( )
2-1 :GCC的使用及其常用选项介绍
【重点】 掌握C语言如何变成机器指令的过程 gcc工具的几个常用选项的意义 【难点】 C编译过程中在gcc工具上的体现 【实验考核】 自己编写程序,利用gcc工具集验证每一步的执行效果 举例说明gcc选项的意义: gcc -I gcc -D gcc -E gcc -S gcc -c
Gcc概述
GCC最初的全名是GNU C Compiler 随着GCC支持的语言越来越多,它的名称变成了GNU Compiler Collection 翻译官 翻译组织 文件后缀名 gcc .c gcc -o output gcc -o 输出的文件名 输入文件名 gcc -v -o
C语言的编译过程
预处理 cpp -o a.i 001.c 替换 【gcc -E】 编译 /usr/lib/gcc/i486-linux-gnu/4.4.3/cc1 -o a.s 001.c 【gcc -S】 汇编 as -o a.o a.s 【gcc -c】 链接 /usr/lib/gcc/i486-linux-gnu/4.4.3/collect2 -o build a.o+... 【gcc -o】 gcc -o build 001.c 【问题】 define include是关键字吗?
C语言常见错误举例
预处理错误: #include "name" #include not find gcc -I跟查找头文件的目录 编译错误: 语法错误 ; { } 链接错误: 原材料不够 undefined reference to `fun' 寻找标签是否实现了,链接时是否加入一起链接 多了 multiple definition of `fun' 多次实现了标签,只保留一个标签实现
预处理的使用
#include 包含头文件 #define 宏 替换,不进行语法检查 #define 宏名 宏体 加括号 #define ABC 5+3 printf("the %d\n",ABC*5); 5+3*5 #define ABC (5+3) #define ABC(x) (5+(x)) #ifdef #else #endif 预定义宏 __FUNCTION__ : 函数名 __LINE__ : 行号 __FILE__ : 文件名
条件预处理举例
调试版本 发行版本 gcc -D : gcc -DABC1 === #define ABC1
宏展开下的#、##
# 字符串化 ## 连接符号 #define ABC(x) #x #define ABC(x) day##x
2-2 :C语言常用关键字及运算符操作
【重点】 掌握C语言的常用关键字及其应用场景,使用技巧 掌握位运算的典型操作 掌握常用的逻辑操作 【难点】 when to do? how to do? why to do? 【实验考核】
关键字
编译器 预先定义了一定意义的 字符串 int a; 32个关键字
数据类型
C 操作对象 :资源/内存{内存类型的资源,LCD缓存、LED灯} C语言如何描述这些资源的属性那? 资源属性【大小】 限制内存(土地)的大小,关键字 int a; sizeof(a) = 4; ==========作业=============== 列出二进制、八进制、十六进制转换的码表
char
硬件芯片操作的最小单位: bit 1 0 软件操作的最小单位: 8bit == 1B 4M 4Mbit Kbit/s KB/S char a; bit a; 应用场景: 硬件处理的最小单位 char buf[xx]; int buf[x]; ASCII码表 8bit 1 2 2 4 3 8 10 ?? 8bit == 256 char a = 300; a++ 301
int
大小: 根据编译器来决定 TC2.0 编译器最优的处理大小: 系统一个周期,所能接受的最大处理单位,int 32bit 4B int 16bit 2B int int a; char a; ============================== 整型常量 char a = 300; 300l 300L 2B 65535 int a = 66535; 进制表示 10 十进制 八进制 十六进制 二进制 3bit 8进制 111 0x7 1000 0x8 int a = 010; //8 12 001 010 4bit 16进制 int a = 0x10 //16
long、short
特殊长度的限制符
unsigned、signed
无符号 : 数据 有符号 : 数字 内存空间的最高字节 是符号位 还是数据 unsigned int a; char a; >> char a = -1; 0xff a>>1 unsigend char b= -1; b>>1
float、double
大小 float 4B double 8B 内存存在形式 0x10 16 0001 0000 16 1.0 0001 0000 (X) 浮点型常量 1.0 1.1 double 1.0f float
void
void a; a++; void fun();
自定义数据类型
C编译器默认定义的内存分配不符合实际资源的形式 自定义 = 基本元素的集合
struct
元素之间的和 struct myabc{ unsigned int a; unsigned int b; unsigned int c; unsigned int d; }; int i; struct myabc mybuf; ------------------------------ 顺序有要求的
union
共用起始地址的一段内存 技巧型代码 union myabc{ char a; int b; }; union myabc abc; int a;
enum
enumerate 一一列举 被命名的整型常数的集合 #define MON 0 #define TUE 1 #define WED 2 enum abc{ MOD = 0,TUE,WED } enum 枚举名称{ 常量列表 }; enum week{ Monday = 0 ,Tuesday =1 ,Wednesday = 2, Thursday,Friday, Saturday,Sunday };
typedef
数据类型的别名 int a =170; int b = 3600; len_t a = 170; time_t b = 3600; int a; a是一个int类型的变量 typedef int a_t; a是一个int类型的外号 a_t mysize; xxx_t : typedef len_t time_t
逻辑结构
CPU顺序执行程序 PC 分支 ---》 选择 循环
if、else
条件 if(条件表达式) xxx; else yyy;
switch、case、default
多分支 swtich(整形数字) float a; switch(a){ case 1.0: break; case 2.0: }
do、while、for
for : 次数 while : 条件 do
continue、break、goto
goto
类型修饰符
对内存资源存放位置的限定 资源属性中位置的限定
auto
默认情况--------> 分配的内存可读可写的区域 auto int a; auto long b; 区域如果再{ },栈空间
register
auto int a; register int a; 限制变量定义在寄存器上的修饰符 定义一些快速访问的变量 编译器会尽量的安排CPU的寄存器去存放这个A,如果寄存器不足时,a还是放在存储器中。 &这个符号对register不起作用 --------------------------- 内存(存储器) 寄存器 0x100 R0,R2
static
静态 应用场景: 修饰3种数据: 1)、函数内部的变量 int fun() { int a; ===> static int a; } 2)、函数外部的变量 int a; ====> static int a; int fun() { } 3)、函数的修饰符 int fun(); ===> static int fun();
const
常量的定义 只读的变量 const int a = 100; a = 200;
extern
外部申明
volatile
告知编译器编译方法的关键字,不优化编译 修饰变量的值的修改,不仅仅可以通过软件,也可以通过其他方式(硬件外部的用户) int a = 100; while( a==100 ); mylcd(); ----------------------- [a] : a的地址 f1: LDR R0,[a] f2: CMP R0,#100 f3: JMPeq f1 ----> JMPEQ f2 f4: mylcd();
杂项
return
返回的概念
sizeof
int a; printf("the a is %d\n",sizeof(a)); sizeof : 编译器给我们查看内存空间容量的一个工具
运算符
算术操作运算
+ 、-
A + B
* 、/、%
* / CPU int a = b*10; CPU可能多个周期,甚至要利用软件的模拟方法去实现乘法 int a = b+10; CPU 一个周期可以处理 %: 0 % 3 = 0 1%3 = 1 2%3=2 3%3=0 4%3=1 ... ... n % m = res [0 - m-1] 取一个范围的数: eg. 给一个任意的数字,得到一个1到100以内的数字? (m% 100)+1 ===> res; 得到M进制的一个个位数 循环数据结构的下标
逻辑运算
真 假 返回结果就是1 0 int a = -1; if(a)
|| 、&&
A || B === B || A != A && B
>、>=、<、<=
!
对比位运算中取反 int a = 0x0; !a if(!a){ } ~a 0xffff
? :
位运算
<< 、>>
左移 : 乘法 *2 二进制下的移位 m m 4: 0 0 1 0 0 8: 0 1 0 0 0 int a = b*32; ===> b [数据、数字] -1 *2 -2: 8bit 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 ==== -1 1 1 1 1 1 1 1 0 右移:除以2 m >> n m/2^n 符号变量有关 int a; a>>n unsigned int a a>>n int a = xxx; while(a){ a = a>>1; } printf("-------------\n");
&、|
& 、 | A & 0 ----> 0 &: 屏蔽 int a = 0x1234; a & 0xff00; 屏蔽低8bit,取出高8bit A & 1 ---> A &:取出 &:清零器 clr | : A | 0 === A 保留 A | 1 === 1 设置为高电平的方法,设置set 设置一个资源的bit5为高电平,其他位不变 int a; a = (a | (0x1 a | (0x1 清除第五位 int a; a = a & 0 1 1 1 1 1 31 a & 31 31 : 32bit ~(0x1 a = a & ~(0x1 a = a & (~(0x1 我们想资源456bit设置为101?
^、~
^ : 1 ^ 1 = 0 0 ^ 0 = 0 1 ^ 0 = 1 算法 AES SHA1 ------------------------------- int fun() { int a = 20; int b = 30; int c; c = a; xxxx-----> a = b; b = c; a = a ^ b; b = a ^ b; a = a ^ b; a = 30 b =20 } ~ 0xf0 ~ 0xffff ff0f
赋值运算
a | (0x1 ~a a = a + b a+=b a = a+b; a+=b a | = (0x1 a &= ~(0x1
=
+=、-=、&=、...
内存访问符号
( )
限制符 (a+b) *c 函数访问 int fun(); fun();
[ ]
数组 内存访问的ID符号 a[1] a[2]
{ }
函数体的限制符 struct abc{xxxxx};
->、.
-> .
&、*
&p a&0x1 *p a*10
逻辑操作
顺序执行
分支执行
循环执行
2-3 :C语言内存空间的使用
【重点】 C语言内存地址访问的方式及使用 连续空间的属性分类及访问 【难点】 空间的属性分类 【实验考核】
指针
指针概述
内存类型资源地址、门牌号的代名词 指针 指针变量 : 存放指针这个概念的盒子 int a; int *p; char *p; C语言编译器对指针这个特殊的概念,有2个疑问? 1、分配一个盒子,盒子要多大? 在32bit系统中,指针就4个字节 2、盒子里存放的地址 所指向 内存的读取方法是什么? 指针指向内存空间,一定要保证合法性 0x12 0001 0010 1.0 0001 0000 * &
指针+修饰符
char *p; int *p;
const
常量、只读【不能变】 内存属性: 1、内存操作的大小 2、内存的变化性,可写可读 char *p; const char *p; 【T】 字符串 “ hello world” "aaa" char const *p; char * const p; 【T】 硬件资源 LCD char *p const; const char * const p ROM
volatile
防止优化指向内存地址 char *p; volatile char *p ; *p == 0x10 while( *p == 0x10 ); xxxx;
typedef
char *p; 什么类型 变量名称; xxx a; int (*p[10])(int ,void (*p)(int)); char *name_t : name_t是一个指针,指向了一个char类型的内存 typedef char *name_t; name_t是一个指针类型的名称,指向了一个char类型的内存 name_t abc;
指针+运算符
++、--、+、-
int a = 100; a+1 int *p = xxx [0x12] p+1 [0x12 + 1*(sizeof(*p))] 指针的加法、减法运算,实际上加的是一个单位,单位的大小可以使用sizeof(p[0]) int *p p+1 char *p p+1 p++ p-- : 更新地址
[]
变量名[ n ] n:ID 标签 地址内容的标签访问方式 取出标签里的内存值
逻辑操作符
>= int *p1; int *p2; p1 > p2 *p1 > *p2 --------- == != 1、跟一个特殊值进行比较 0x0 : 地址的无效值,结束标志 if( p == 0x0) NULL 2、指针必须是同类型的比较才有意义 char * int *
多级指针
int **p; 存放地址的地址空间 char **p; p[0] p[1] ... p[n] p[m] == NULL ----> 结束了
数组
内存分配的一种形式
数组的定义
定义一个空间: 1、大小 2、读取方式 数据类型 数组名[m] m 的作用域是在申请的时候 数组名是一个常量符号,一定不要放到=的左边 char buf[100]; buf = "hello world"; int a[100]; 越界 a[10]
数组空间的初始化
空间的赋值 按照标签逐一处理 int a[10]; [ 0 - 9 ] a[0] = xx a[1] = yy; 程序员这样赋值,工作量比较大,能不能让编译器进行一些自动处理,帮助程序员写如上的程序 ----》空间定义时,就告知编译器的初始化情况,空间的第一次赋值,初始化操作 int a[10] = 空间; C语言本身,CPU内部本身一般不支持空间和空间的拷贝 int a[10] = {10,20,30}; ====> a[0] = 10; a[1] = 20; a[2] = 30; a[3]=0; ---------------------------------------------------------------------- 数组空间的初始化 和 变量的初始化 本质不同,尤其在嵌入式的裸机开发中,空间的初始化往往需要库函数的辅助
char
char buf[10] = {'a','b','c'}; buf当成普通内存来看,没有问题 buf当成一个字符串来看,最后加上一个'\0' 0 字符串的重要属性,结尾一定有个'\0' char buf[10] = {"abc"}; char buf[10] = "abc"; buf[2] = 'e'; char *p = "abc"; p[2] = 'e'; char buf[] = "abcd"; //5 char buf[10] = "abc"; buf = "hello world" 第二次内存初始化,赋值? 逐一处理 buf[0] = 'h' buf[1] = 'e' ... buf[n] = 'd', buf[n+1] = 0;
strcpy,strncpy
一块空间,当成字符空间,提供了一套字符拷贝函数 字符拷贝函数的原则: 内存空间和内存空间的逐一赋值的功能的一个封装体 一旦空间中出现了0这个特殊值,函数就即将结束。 strcpy(); char buf[10] = "abc"; buf = "hello world"; strcpy(buf,"hello world");
非字符串空间
字符空间 ASCII码编码来解码的空间,----》给人看 %s abc 'a ' 'b' ' c' \0作为结束标志 非字符空间 数据采集 0x00 - 0xff 8bit 开辟一个存储这些数据盒子 char buf[10]; ----> string unsigned char buf[10];----> data buf = "abc"; unsigned char *p = sensor_base; 只管逐一拷贝,结束在哪里?只能定义个数 拷贝三要素: 1、src 2、dest 3、个数
memcpy
int buf[10]; int sensor_buf[100]; memcpy(buf,sensor_buf,10*sizeof(int)); unsigned char buf1[10]; unsigned char sensor_buf[100];// 00 00 00 23 45 78 strncpy(buf,sensor_buf,10) memcpy(buf,sensor_buf,10*sizeof(unsigned char));
指针与数组
int a[100];
指针数组
int a[100] char * a[100]; sizeof(a) = 100 * 4; int b; sizeof(b) char **a;
多维数组
线性 只是针对人和人交流的方便些来实现,对于二位数组空间如何在内存的表现形式上,我们不考虑 int abc[3][5]; 3*5*sizeof(int) abc[1] : 空间,地址 abc[1][2]
数组名的保存
定义一个指针,指向int a[10]的首地址 定义一个指针,指向int b[5][6]的首地址 int *p1 = a; int **p2 = b; int *p; int *p[5]; int a; int a[5]; int *p[5]; int (*p)[5]; int b[2][3][4]; int (*p)[3][4];
结构体
字节对齐
char a; int b; 1 + 4 = 5 效率,希望牺牲一点空间换取时间的效率 最终结构体的大小一定是4的倍数 结构体里成员变量的顺序不一致,也会影响到他的大小
位域
内存分布图
内存的属性: 1、大小 2、在哪里 int a; 默认方式 编译 ---》汇编 ---》链接 *.o build 内核空间 应用程序不许访问 ------------------------------- 3G 栈空间 局部变量 RW ----------- 运行时的堆空间 malloc ----------- 全局的数据空间 (初始化的,未初始化) static RW data bss 只读数据段 "hello world" 字符串常量 R TEXT 代码段 code R TEXT ------------ 0x0 :
栈空间
运行时,函数内部使用的变量,函数一旦返回,就释放,生存周期是函数内
堆空间
运行时,可以自由,自我管理的分配和释放的空间,生存周期是由程序员来决定 分配: malloc(),一旦成功,返回分配好的地址给我们,只需要接受,对于这个新地址的读法,由程序员灵活把握,输入参数指定分配的大小,单位就是B。 char *p; p = (char *)malloc(100); if(p == NULL){ error } void fun() { char *p; p = (char *)malloc(100); return ; } int a[5]; malloc(5*sizeof(int)) 释放: free(p);
只读空间
静态空间,整个程序结束时释放内存,生存周期最长
段错误分析
2-4 :C语言函数的使用
【重点】 函数地址的表示方式 函数输入参数的表现形式及什么时候使用 函数返回值地址表现形式的应用场景及注意事项 【难点】 函数指针的意义 二级指针在函数输入参数的使用 【实验考核】
函数概述
一堆代码的集合,用一个标签去描述它 复用化 标签 ----- 函数名 函数 数组,函数具备3要素: int *p; int a[100]; 1、函数名 (地址) 2、输入参数 3、返回值 在定义函数时,必须将3要素告知编译器。 int fun(int,int,char) { xxx } 如何用指针保存函数那? char *p; char(*p)[10]; int (*p)(int,int,char); 定义函数,调用函数 int fun(int a,char b) { xxxx } int main() { fun(10,2); } char buf[100]; buf[10];
输入参数
承上启下的功能 调用者: 函数名(要传递的数据) //实参 被调者: 函数的具体实现 函数的返回值 函数名(接收的数据) //形参 { xx xxx } 实参 传递给 形参 传递的形式: 拷贝
值传递
特点: void fun(int a) { a = xx; a = sha md5 yy } int main() { int a = 20; fun(a); printf a ==? } 上层调用者 保护自己空间值不被修改的能力
地址传递
上层,调用者 让下层 子函数 修改自己空间值的方式 类似结构体这样的空间,函数与函数之间调用关系---> 连续空间的传递 void fun(char a); int main() { char a = 'e'; fun(a); a == 'c' } void fun(char *b); int a = 10; fun(&a); a ===? 10 int a; scanf("%d",a); scanf("%d",&a)
空间的读写
void fun(char *p); const char *p : 只读空间,为了空间看看 char *p : 该空间可能修改 strcpy(); sprintf(); void fun(const char *p) { // p[n] = '1'; }
作用
1、修改 int * short * long * 2、空间传递 2.1 子函数看看空间里的情况 const * 2.2 子函数反向修改上层空间里的内容 char * void * void fun(int *p); int buf[10]; fun(buf); int a = 10; fun(&a); a != 10 void fun(const int *p); void fun(const char *p); p[1000] p[100] p[10000] 空间:空间首地址、结束标志 结束标志:内存里面存放了0x00 (1B),字符空间 非字符空间 0x00,不能当成结束标志
连续空间的传递
1、数组 数组名 --- 标签 实参: int abc[10]; fun(abc) 形参: void fun(int *p) void fun(int p[10]) 2、结构体 结构体变量 struct abc{int a;int b;int c;}; struct abc buf; 实参: fun(buf); fun(&buf) 形参: void fun(struct abc a1) void fun(struct abc *a2)
字符空间
void fun(char *p) { p[1000] = '1'; char buf; buf = p[100]; } ------> void fun(char *p) const char *p { int i = 0; while(p[i]){ p[i]操作 p[i] =x; a=p[i] + - i++; } }
strlen
int strlen(const char *p) { int i = 0; /*错误处理,判读输入参数是否合法*/ if(p == NULL){ // return ... } /*内存处理,从头到尾逐一处理*/ while(p[i]){ //+++++++++++ i++; } }
strcpy
void strcpy(char *dest,const char *src); " " ---> 初始化const char * char buf[10] ---> 初始化char *
非字符空间
unsigned char *p; 结束标志:数量 (B) int *p unsigned char *p short *p struct abc *p void * : 数据空间的标识符 大小 void fun(unsigned char *p) { p[100] = xx p[1000] = yy; } void fun(unsigned char *p,int len) { int i; for(i = 0; i p[i] = ; a= p[i] //++++++++ -------- } } int main() { struct sensor_data buf; int buf1[100]; fun(&buf,sizeof(buf)*1) }
memcpy
void *
int fun(void *buf,int len) { unsigned char *tmp = (unsigned char *)buf; tmp[i] i++ len }
返回值
提供启下功能的一种表现形式
基本语法
返回类型 函数名称(输入列表) { return } 调用者 a = fun(); 被调者: int fun() { return num; } 拷贝 返回类型 基本数据 指针类型(空间) 数组(X)
返回基本数据类型
int fun(void) { return } struct abc fun(void); main: int fun1(void); int a=0; a = fun1(); void fun2(int *p); int a = 0; fun2(&a); a int [2] fun(void); int fun(int *); int *fun1(void); int main() { int *p; p = fun1(); } void fun2(int **p) int main() { int *p; int p fun2(&p); p }
返回连续空间类型
指针作为空间返回的唯一数据类型 int *fun(); 地址:指向的合法性 作为函数的设计者,必须保证函数返回的地址所指向的空间是合法。【不是局部变量】 使用者: int *fun(); int *p = fun(); int p[100]; (X)
函数内部实现
基本数据类型 fun(void) { 基本数据类型 ret; xxxx ret = xxxx; return ret; } int fun() { int ret = 0; count++; ret = xxx; return ret; } char *fun() { char *s = NULL; char buf[]; return buf; }
1、静态区
static
2、只读区
字符串常量 不太常用
3、堆区
malloc free
2-5 :常见面试题目讲解
嵌入式工程师必备0x10道题目
宏定义
1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define 宏名 宏体 宏名 : 大写字母表示 //#define SECOND_OF_YEAR 123456 #define SECOND_OF_YEAR (365*24*3600)UL 8bit : 0 - 255 256 16bit: 0 - 65535 INT 的常量 255 256 365*24*3600
数据声明
用变量a给出下面的定义 a) 一个整型数(An integer) int a; b)一个指向整型数的指针( A pointer to an integer) int *a; c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an integer) int* *a; int **a; d)一个有10个整型数的数组( An array of 10 integers) int a[10]; e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers) int* a[10]; f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers) int [10] *a ---> int (*a)[10] g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer) int fun(int) *a ---> int (*a)(int) h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer ) int (*a[10])(int)
修饰符的使用总结
关键字static的作用是什么? 1、修饰局部变量 默认局部变量 在 栈空间存在,生存期比较短 局部静态化,局部变量 在 静态数据段保存,生存期非常长 2、修饰全局变量 防止重命名,限制变量名只在本文件内起作用 3、修饰全局函数 防止重命名,限制该函数只在本文件内起作用 关键字const有什么含意? C :只读,建议性 不具备强制性 != 常量 const int a = 100; c++ : 常量 关键字volatile有什么含意?并给出三个不同的例子。 防止C语言编译器的优化。 他修饰的变量,该变量的修改 可能通过第三方来修改
位操作
嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。 unsigned int a; a |= (0x1 a &= ~(0x1
访问固定内存位置
在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。 int *p = (int *)0x67a9; p[0] = 0xaa66; *p = 0xaa66; *((int*)0x67a9) = 0xaa66; ((void (*)(void))0x67a9) ();
公司面试题目
1、统计一个int空间里1的个数 2、给你一个带有空格的字符串,删除其中空格