【写给自己的开发知识树】——十万个问题之编程相关

定义局部变量而不初始化,其值为什么是随机的?

因为定义时相当于在栈上移动指针找到一块没人在用的空间给变量,但是栈是会被人反复使用的(脏的),所以这块空间上遗留着上次使用的内容。

结构体为什么要对齐访问?

主要是为了配合硬件,提高访问效率。

为什么需要条件编译?

有时候我们希望程序有多种配置,我们在编写源代码时写好了各种配置的代码,然后给个配置开关,在源代码级别区修改配置开关来让程序编译出不同的效果。

为什么会有函数?

这是人的需要不是机器的需要。可以分化问题,易于分工,有利于程序的组织。

为什么需要回调函数

实现方:提供回调的地方
执行方:调用回调的地方
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)[;]

在其他情况下都会编译报错:形如作为参数、条件语句

ifmin(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,会偏移掉整个数组

数组退化成指针是什么意思

意思是数组名被编译器当成指向数组第一个元素地址的指针。
这种情况只出现在数组作为表达式或函数参数的时候。
数组声明时的数组名就是地址不是指针。

坚持积累

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值