C++,调用函数时,根据不同的label来实现重载!
例如:
int memcmp(void *p)
{
int n = 17;
int m = memcmp(&n)
}
如果是C,翻译成汇编语言:
CALL <memcmp>
如果是C++,翻译成汇编语言:
CALL <memcmp_void_p>
再如:
int memcmp(void *v1, void *v2, int size)
如果是C,翻译成汇编语言:
CALL <memcmp>
如果是C++,翻译成汇编语言:
CALL <memcmp_void_p_void_p_int>
对于C++,入参的不一致 → “链接”错误→相比于C更安全,但也更死板!
| 数据类型 | 对齐 |
|---|---|
| char | 1 |
| short | 2 |
| int | 4 |
| 其它 | 4 |
void *vp =...
*(short *)vp = 7; // 50% → bus error
*(int *)vp = 7; // 75% → bus error
*(char *)vp = 7; // OK!!!
缓冲区溢出(buffer overflow)是指下面这种情况:
int main()
{
int i;
int array[4];
for(i = 0; i < 4; i++) {
array[i] = 0;
};
return 0;
}

int main()
{
int i;
short array[4];
for(i = 0; i <= 4; i++) {
array[i] = 0;
};
return 0;
}

void foo()
{
int array[4];
int i;
for(i = 0; i <= 4; i++) {
array[i] -= 4;
}
}

void DeclearAndInitArray()
{
int array[100];
int i;
for(i = 0; i < 100; i++) {
array[i] = i;
}
}
void PrintArray()
{
int array[100];
int i;
for(i = 0; i < 100; i++) {
printf("%d\r\n", array[i]);
}
}
int main(int argc, char **argv)
{
DeclearAndInitArray();
PrintArray();
}
为什么没有进行函数之间的数据传递,仍然能够正确打印出来 0~99呢?
答:调用DeclearAndInitArray(),活动记录中有408(4+100x4+1x4)个字节,数组占据了saved PC下面的400个字节,DeclearAndInitArray()函数RET后,虽然这存放数组的400个字节已经出栈,但是并没有被清0;
继续调用PrintArray(),它的活动记录将占用刚才DeclearAndInitArray()的位置,并且活动记录的结构与DeclearAndInitArray()一模一样,此时,直接打印数组中的数据,会成功打印出DeclearAndInitArray()留在内存中的0~99。
这个特性能用在哪里?答:中断服务函数中!
留给中断服务函数处理事务的时间是很短的,我们可以先构造好一些常量数据,存放在“栈”中某个地方,这样在中断服务函数中就免于构造这些数据的麻烦了!
为了实现“可变参数”…
通常有“可变参数”的 编程语言 ,函数入参都是从右向左压栈!
int printf(const char *control, ...);
…是可变参数!可以是任何类型数据,并且“个数”不限!
printf("%d + %d = %d \r\n", 4, 4, 8);

struct type {
int code;
};
struct type_one {
int code;
...
};
从上到下压栈,可以得到code与结构体变量基地址的距离!反着来,得到这个“距离”就依赖于总长度了,会变得复杂!!!
比如咱们的网络IP地址,以前的网络地址是IPv4的,用4个字节表示IP地址,某天大家意识到,4个字节的IP地址会很快被用光,因此开发了6个字节的IP地址。IPv4和IPv6对应着不同的结构体,我们希望IPv6能够兼容IPv4,所以IPv6的前4个字节结构与IPv4是一样的!要是IPv6的前4个字节后入栈,很难得到其余结构体变量基地址的距离了,会给变成带来麻烦!
int main()
{
int numAgents = 10;
int numTickets = 150;
for(int agent = 1; agent <= numAgents; agent++) {
SellTickets(agent, numTickets / numAgets);
}
return 0;
}
void SellTickets(int agentID, int numTickestoSell)
{
while(numTickestoSell > 0) {
printf("Agent %d sells a ticket \r\n", agentID);
numTickestoSell--;
}
printf("Agent %d: All down.\r\n", agentID);
}
预期结果:
打印出来160行;其中 Agent %d: All down.\r\n 占用10行。
上面这样实现,每个agent会依次买票,并不会10个 agents 同时一起买票!
希望使用1个“线程”包。
int main()
{
int numAgents = 10;
int numTickets = 150;
InitThreadPackage(false);
for(int agent = 1; agent <= numAgents; agent++) {
char name[32];
sprintf(name, "Agent %s Thread", agent);
ThreadNew(name, SellTickets, 2, agent, numTickets / numAgets); // 把狗狗们都放到起跑线上
RunAllThreads(); // 把门打开,大家一起跑啊!
return 0;
}
void SellTickets(int agentID, int numTickestoSell)
{
while(numTickestoSell > 0) {
printf("Agent %d sells a ticket \r\n", agentID);
numTickestoSell--;
if(RandomChance(0.1)) {
// 模拟条件:10% 概率被强制暂停运行
ThreadSleep(1000);
}
}
printf("Agent %d: All down.\r\n", agentID);
}
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删