微前端架构如何改变企业的开发模式与效率提升
624
2022-08-27
ANSI C (6) —— 指针、断言、信号、跳转
指针
下面的三条语句是等价的,但是我们常常使用的是第一种形式int *p,同时我们注意,他们是在初始化p而不是*p。
#include
指向void 类型的指针可以指向其他的任何的数据类型变量的地址。任何类型的指针也可以指向void.
int main(){ int a=12; double b=12.99; void *p=&a; printf("%d\n",*((int *)p)); p=&b; printf("%lf\n",*((double *)p)); return 0;}/*1212.990000*/
我们可以在变量value前使用&但是不能在value ‘计算符’ ‘常量或变量’前加&,因为value ‘计算符’ ‘常量或变量’得到的是常量
int a=12,b=10; int *p=&(a+b); // error: lvalue required as unary '&'
数组和指针
数组名是一个指针常量,数组定义时设置成数组第一个单元的地址,从此以后就不能修改,int a[3]; a=...是错误的。 但是修改数组的单元是合法的,a[1]=...。 指针变量可以进行赋值操作。
#include
利用数组首地址输出字符串:
#include
多级间接访问
指向指针的指针,比如 int ** p (指向int型变量的指针变量的指针变量) 一次类推还有,int *** p (p是类型为int***的变量,三个星号,代表着三次间接访问) 如下列代码:
int a = 12; int* p1 = &a; int** p2 = &p1; int*** p3 = &p2; printf("%d\n",***p3); ***p3 = 14; printf("%d\n",a);
常量指针与指针常量
const修饰的是数据类型,则为常量指针。(const char* p) const修饰的是指针本身,那么则为指针常量。(char* const p)
#include
指向函数的指针
int (*p)(char ) /* p是一个指向参数为char,返回值是int的函数的指针 */int *p(char ) /* p是函数名,该函数的参数为char,返回值类型是int * */
调用相关的方式: (*p)(ch) 或者 p(ch) 比如:
int get(char ch){ return ch;}int main(){ int (*p)(char); p = &get; printf("%d\n",p('A')); printf("%d\n",(*p)('A')); return 0;}/*6565*/
函数指针应用: 在程序中fork一个子进程,在子进程中弹出选择框,询问用户喜欢哪一类操作系统,然后回到父进程正常退出。
#include
执行:
$ ./func please tell me which OS do you like most:1.windows2.linux/Unix3.Mac OSenter a number: 0please tell me which OS do you like most:1.windows2.linux/Unix3.Mac OSenter a number: 2linux OS end....
restrict指针的疑惑
restrict是c99标准引入的,用于限定和约束指针,它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改, 任何同样指向这个内存单元的其他指针都是无效指针。 但是下面的例子不是在说“无效指针是有效的”吗?
#include
执行:
[edemon@CentOS workspace]$ gcc -std=c99 restrict.c [edemon@CentOS workspace]$ ./a.out 23 2324 24[edemon@CentOS workspace]$ gcc -std=gnu99 restrict.c [edemon@CentOS workspace]$ ./a.out 23 2324 24
断言
断言assertion是一个程序特定执行点上必须满足的条件,如果断言不满足,系统将打印错误。 例如:
#include
使用断言需要一定的系统开销,可以在assert.h前增加宏NDEBUG来使得断言设定失效。
#define NDEBUG#include
信号
程序执行的过程中如果出现错误,计算机系统将产生一个信号来表示发生了异常,C可以调用自己的函数来处理这些信号。 也即是异常处理。 相关的函数是signal() sighandler_t signal(int signum, sighandler_t handler); signal()返回上一个信号处理函数的handler的返回值。 三种方式处理异常信号:
function | effect |
SIG_DFL | 终止程序 |
SIG_IGN | 忽略 |
自定义函数 | 自定义处理动作 |
比如程序:
#include
即使按下ctrl + c,系统也不会终止程序。 我们也能自定义信号处理函数,比如javascript:void(0) 的《11.自定义中断信号SIGINT的处理函数》。
跳转
这里说的跳转不是goto,而是setjmp(), longjmp().前者设置了跳转的终点,longjmp()则是跳转的入口。
void longjmp(jmp_buf env, int val);If longjmp() is invoked with a second argument of 0, 1 will be returned instead.void int
例子:
#include
执行:
[edemon@CentOS workspace]$ gcc jmp.c [edemon@CentOS workspace]$ ./a.out endend
goto语句是无法实现不同函数间的跳转的。如上的例子,我们修改成:
#include
不出现意外的话,编译的时候会有类似这样的信息:
error: label ‘tag’ used but not defined goto
其他
块和局部变量
C可以使用块{}来影响变量的作用范围。
#include
关于char的负数问题
关于char的负数问题: ASCII码只有0~127,但是中文是用多字节来表示的,随着字符编码的不同,每一个汉字所占的字节数也是不同的,例如GBK一个汉字两个字节,utf-8一个汉字三个字节。 比如:
/*Linux CentOS.com 2.6.32-642.6.2.el6.i686 #1 SMP Wed Oct 26 06:14:53 UTC 2016 i686 i686 i386 GNU/Linux*/#include
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~