目录
定义局部变量而不初始化,其值为什么是随机的?
因为定义时相当于在栈上移动指针找到一块没人在用的空间给变量,但是栈是会被人反复使用的(脏的),所以这块空间上遗留着上次使用的内容。
结构体为什么要对齐访问?
主要是为了配合硬件,提高访问效率。
为什么需要条件编译?
有时候我们希望程序有多种配置,我们在编写源代码时写好了各种配置的代码,然后给个配置开关,在源代码级别区修改配置开关来让程序编译出不同的效果。
为什么会有函数?
这是人的需要不是机器的需要。可以分化问题,易于分工,有利于程序的组织。
为什么需要回调函数
实现方:提供回调的地方
执行方:调用回调的地方
1、降低模块耦合性(降低依赖性、关联性),提高模块独立性,避免模块之间你中有我我中有你。
2、异步回调,可以将耗时的操作隐藏在执行方,不影响实现方其它操作。SetTimer
3、多态效果,可以让实现方,根据自己的需要定制执行方的不同形态;
例如功能模块和业务模块之间
负数的/和%
#include <stdio.h>
int main()
{
int a=-3, b=2,c=3,d=-2;
int q,r,m,n,x,y,h,w;
q = a / b;
r = a % b;
m = c / d;
n = c % d;
x = a / d;
y = a % d;
h = c / b;
w = c % b;
printf("q=%d, r=%d\n" , q , r);
printf("m=%d, n=%d\n" , m , n);
printf("x=%d, y=%d\n" , x , y);
printf("x=%d, y=%d\n" , h , w);
return 0;
}
q=-1, r=-1
m=-1, n=1
x=1, y=-1
x=1, y=1
0、NULL强转有什么用
比如linux kernel下有链表定义LINK_NODE
typedef struct _LINK_NODE
{
struct _LINK_NODE* prev;
struct _LINK_NODE* next;
}LINK_NODE;
然后我们自定义的结构体如下,在只知道LINK_NODE的情况下,如何使用DATA_TYPE访问value呢?
方法是head的地址减去head相当于结构体的偏移,就可以得到结构体的首地址,再强转后就是DATA_TYPE了。
typedef struct _DATA_TYPE
{
LINK_NODE head;
int value;
}DATA_TYPE;
#define GET_DATA_ADDRESS(pNode, DATA, head) \
(DATA*)((char*)(pNode) - (&((DATA*)(0))->head))
结构体最后定义char[0]有什么用
typedef struct _DATA
{
int len;
char flage;
int value;
char a[0];
}DATA;
这个a可以用来实现可变长的结构体,用的时候malloc出来就可以了。其本身不占内存空间,但是可以访问。如果用其他方式比如char a[1]那就还得占空间。
(void) (&min1 == &min2)的作用
在linux 内核中,这个起到警告的作用。如果两个变量不是相同类型,进行==就会告警。
宏定义加括号的作用
例如:
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
如果不加(),那这个宏定义只能作为一条语句的方式使用:形如
单独一行的min(1,2)[;]
在其他情况下都会编译报错:形如作为参数、条件语句
if(min(1,2)){}
num = 1?min(2,3):4;
printf("%d\n", min(1,2));
为什么C++中线程函数必须是static的
因为C++中非static函数会默认加上一个参数——this,这样就不符合线程函数的参数定义了。
为什么一直说C语言运行速度快
1、C语言不会进行内存泄漏、越界等检查,少了步骤。
2、C语言编译完成后生成机器码,可直接被CPU识别运行,不需要通过虚拟机转换。
C种什么是声明、定义
声明:可以出现多次,用来说明这个变量定义了,但是在其他地方(如其他文件)。
定义:只能出现一次,确定变量的类型并分配内存
C用编译器编译,那用运行器运行吗?
都知道编写C程序,然后编译成可执行文件,然后运行。那谁在运行呢?
这里的运行器其实是shell+系统。shell会调用一个特殊的系统调用,根据可执行文件创建
新的进程、内存环境,然后系统就会去走到这个程序了,运行起来了。
为什么对数组名取地址后的值和数组名的值一样
数组名的值 == 数组中第一个元素的地址
数组名取地址 == 整个数组的首地址
整个数组的首地址 == 数组首元素的地址
但是要注意的是,取地址后有个区别:
&数组名+1,会偏移掉整个数组
数组退化成指针是什么意思
意思是数组名被编译器当成指向数组第一个元素地址的指针。
这种情况只出现在数组作为表达式或函数参数的时候。
数组声明时的数组名就是地址不是指针。