printf参数的问题
根据前面的某一篇的文章,可以清楚的看到:对于每一个函数,通过这个函数的[ebp+x]就可以直接访问到它调用的时候传进来的形参的值,通过[ebp-x]就可以直接访问它的局部变量。
所以printf这个函数不定参数的实现是通过栈机制实现的,在传入实参的时候,从右向左一次把各个参数压入栈,但是这些压入栈的数据是没有类型区分的,就是把相应的数据依次放到栈中排好。最后压入栈的那个参数“%d%d%d”等类似的参数,才是决定printf参数类型的东西。等到程序的执行控制权到达printf中以后,printf就从传入的实参的起始位置,按照“%d%d%d”等类似的字符串来控制类型依次输出。这个字符串控制输出的个数和类型。同时这个字符串没有越界检测。
int a = 10; printf("%d %d %d\n", a);
这种打印的越界是不会检测的,函数调用前实参压栈a,然后压栈"%d %d %d\n"类型控制字符串。最后在printf中函数调用的时候,从之前压入的实参中依次打印出三个int,虽然压入栈的实参只有一个int,但是没有越界检测,所以还是会打印三个int。
来分析一个实际的问题:
char s[] = "123", *p; p = s; printf("%c%c%c\n", *p++, *p++, *p++);
这个问题要注意printf和*p++这两个知识点,printf的参数压栈是从右向左的,并且注意*p++的执行顺序。所以第一个压栈的参数是1然后压栈2,然后压栈3。打印的时候一次打印321。