在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Outline
====打开Wall警告==== 一个好的习惯是打开gcc的-Wall选项,也就是让gcc提示所有的警告信息,不管是严重的还是不严重的,然后把这些问题从代码中全部消灭。比如把上例中的printf("Hello, world.\n");改成printf(0);然后编译运行: ====转移符号==== 表 2.1. C标准规定的转义字符 \' 单引号'(Single Quote或Apostrophe)
\" 双引号"
\? 问号?(Question Mark)
\\ 反斜线\(Backslash)
\a 响铃(Alert或Bell)
\b 退格(Backspace)
\f 分页符(Form Feed)
\n 换行(Line Feed)
\r 回车(Carriage Return)
\t 水平制表符(Horizontal Tab)
\v 垂直制表符(Vertical Tab)
====sizeof(数据类型)==== rhel5.5版本: short: 2 int: 4 long: 4 char: 1 float: 4 double:8 long double: 12short: 2 int: 4 long: 4 char: 1 float: 4 double:8 long double: 12
====math.h==== gcc main.c -lm ====函数调用的本质==== #include<stdio.h> void foo (void) { int i; printf("%d\n", i); i = 777; } int main(void) { foo(); #if 1 printf("hello\n"); //有无此句对函数结果的影响,分析! #endif foo(); return 0; }
====语句块==== 语句块中也可以定义局部变量,例如: void foo(void) { int i = 0; { int i = 1; int j = 2; printf("i=%d, j=%d\n", i, j); } printf("i=%d\n", i); /* cannot access j here */ } 和函数的局部变量同样道理,每次进入语句块时为变量j分配存储空间,每次退出语句块时释放变量j的存储空间。语句块也构成一个作用域,和例 3.6 “作用域”的分析类似,如果整个源文件是一张大纸,foo函数是盖在上面的一张小纸,则函数中的语句块是盖在小纸上面的一张更小的纸。语句块中的变量i和函数的局部变量i是两个不同的变量,因此两次打印的i值是不同的;语句块中的变量j在退出语句块之后就没有了,因此最后一行的printf不能打印变量j,否则编译器会报错。 ====快速跳转==== gotogoto语句过于强大了,从程序中的任何地方都可以无条件跳转到任何其它地方,只要在那个地方定义一个标号就行, 唯一的限制是goto只能跳转到同一个函数中的某个标号处,而不能跳到别的函数中。 setjmp & longjmpC标准库函数setjmp和longjmp配合起来可以实现函数间的跳转,但只能从被调用的函数跳回到它的直接或间接调用者(同时从栈空间弹出一个或多个栈帧),而不能从一个函数跳转到另一个和它毫不相干的函数中。setjmp/longjmp函数主要也是用于出错处理,比如函数A调用函数B,函数B调用函数C,如果在C中出现某个错误条件,使得函数B和C继续执行下去都没有意义了,可以利用setjmp/longjmp机制快速返回到函数A做出错处理。 ====struct初始化==== struct segment { struct complex_struct start; struct complex_struct end; }; 从第 1 节 “复合类型与结构体”讲的Initializer的语法可以看出,Initializer也可以嵌套,因此嵌套结构体可以嵌套地初始化,例如: struct segment s = {{ 1.0, 2.0 }, { 4.0, 6.0 }}; 也可以平坦(Flat)地初始化。例如: struct segment s = { 1.0, 2.0, 4.0, 6.0 }; 甚至可以把两种方式混合使用(这样可读性很差,应该避免): struct segment s = {{ 1.0, 2.0 }, 4.0, 6.0 }; 利用C99的新特性也可以做Memberwise Initialization,例如[15]: struct segment s = { .start.x = 1.0, .end.x = 2.0 }; //部分初始化,C99的新特征 ====对齐原则==== 一、 ====数据段的分配==== 实例: ====string==== 注意每个字符末尾都有一个字符'\0'做结束符,这里的\0是ASCII码的八进制表示,也就是ASCII码为0的Null字符,在C语言中这种字符串也称为以零结尾的字符串(Null-terminated String)。数组元素可以通过数组名加下标的方式访问,而字符串字面值也可以像数组名一样使用,可以加下标访问其中的字符: char c = "Hello, world.\n"[0]; //这种手法,貌似很拽!
char c = '@'; char arr[] = "hello, world"; char str0[4] = "012"; //自动加了null char str1[4] = "0123"; //因为字符串长度正好,所以没哟自动加 '\0' ,这个要注意。 char str2[4] = "0123456"; //舍去了多余的初始化,当然也没有自动加 '\0'。 result: @ d l r o w , o l l e h 2 1 0 3 2 1 0 3 2 1 0
====Multi-dimensional Array==== 注意,除了第一维的长度可以由编译器自动计算而不需要指定,其余各维都必须明确指定长度。
Python调用 .soFrom: Python调用Linux下的动态库(.so) (1) 生成.so:.c to .so lolo@-id:workme$ gcc -Wall -g -fPIC -c linuxany.c -o linuxany.o (2) 调用.so:Python call .so #!/usr/bin/python from ctypes import * import os //参数为生成的.so文件所在的绝对路径 libtest = cdll.LoadLibrary(os.getcwd() + '/linuxany.so') //直接用方法名进行调用 print libtest.display('Hello,I am linuxany.com') print libtest.add(2,2010) (3) 可能遇到的问题: version `GLIBC_2.27' not found Download updated version from: https://mirror.freedif.org/GNU/libc/
编译链接问题relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
Ref: 程序内存布局 PPT(系统概览,亦是面试常见问题) Linux 内核的通用链表函数库/* implement */
应用位域的例子 - 段描述符Ref: 结构体对齐(图解)与位域
Linux的虚拟内存管理用户地址空间?? 内核地址空间??
main() 不是第一个函数f()赋值给g的时候还是要先执行一下子的,然后再执行main。 #include <stdio.h> int f(), g = f(); int main() { } int f() { printf("Hello world!\n"); return 0; }
执行顺序是:先构造,再main,最后析构。 #include <stdio.h> static __attribute__((constructor)) void before() { printf("Hello\n"); } static __attribute__((destructor)) void after() { printf("World\n"); } int main() { printf("main()\n"); return 0; }
钩子函数:atexit(): #include <stdio.h> #include <stdlib.h> void f(void) { printf("Bye! World 2\n"); } void g(void) { printf("Bye! World 1.\n"); } void y(void) { printf("Bye! World 3.\n"); } int main() { atexit(y); atexit(g); printf("main()\n"); atexit(f); return 0; } OUTPUT: main() Bye! World 2 Bye! World 1. Bye! World 3.
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论