1.//========================================================================================================
/*2018-05-25
File: push_test1
功能:手动确定可变参数的标准printf()函数
*/
#include "stdio.h"
struct person
{
char * name;
int age;
char score;
int id;
};
/*参考标准函数:int printf(const char * format, ...)
*依据:x86平台,函数调用时参数的传递是使用堆栈来实现的
*目的:将所有传入的参数全部打印出来
*/
int push_test(const char * format, ...)
{
volatile char *p = (char *)&format;
//char *p = &format;
int i;
struct person per;
char c;
double d;
printf("arg1: %s\n", format);
//printf("&format = %p\n", p);
p = p + sizeof(char *);
i = *((int *)p);
p = p + sizeof(int);
printf("arg2: %d\n", i);
//printf("&i = %p, p = %p\n", &i, p);
per = *((struct person*) p);
p = p + sizeof(struct person);
printf("arg3: .name = %s, .age = %d, .score = %c, .id = %d\n", per.name, per.age, per.score, per.id);
//printf("&per = %p, p = %p\n", &per, p);
c = *((char *)p);
p = p + ((sizeof(char) + 3) & (~3));
printf("arg4: c = %c\n", c);
d = *((double *)p);
p = p + (sizeof(double) & (~3));
printf("arg5: d = %lf\n", d); //输出格式符为 %f或%lf,输出结果都一样 arg5: d = 3.140000
return 0;
}
int main(void)
{
struct person per = {"zhangsan", 15, 'A', 003};
push_test("abcd", 123, per, 'W', 3.14);
return 0;
}
/*
1.第31行屏蔽前后,程序的运行结果:
【屏蔽前】book@www.100ask.org:~/workbook/hardware/UART/push_test1$ ./push_test
arg1: abcd
arg2: -134643712
&i = 0xffc48054, p = 0xffc48050
arg3: .name = <?, .age = -3899308, .score = , .id = -3899308
【屏蔽后】book@www.100ask.org:~/workbook/hardware/UART/push_test1$ gcc -m32 -o push_test push_test.c
book@www.100ask.org:~/workbook/hardware/UART/push_test1$ ./push_test
arg1: abcd
arg2: 123
arg3: .name = zhangsan, .age = 15, .score = A, .id = 3
book@www.100ask.org:~/workbook/hardware/UART/push_test1$
2.
push_test.c:30:9: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
printf("&format = %#x\n", p);
3.屏蔽第24,31,37,43句前,程序的运行结果:
【屏蔽前】book@www.100ask.org:~/workbook/hardware/UART/push_test1$ gcc -m32 -o push_test push_test.c
book@www.100ask.org:~/workbook/hardware/UART/push_test1$ ./push_test
arg1: abcd
&format = 0xffc23e5c
arg2: -135135232
&i = 0xffc23e64, p = 0xffc23e60
arg3: .name = <?, .age = -4047260, .score = , .id = -4047260
&per = 0xffc23e6c, p = 0xffc23e64
book@www.100ask.org:~/workbook/hardware/UART/push_test1$
【屏蔽后】
book@www.100ask.org:~/workbook/hardware/UART/push_test1$ gcc -m32 -o push_test push_test.c
book@www.100ask.org:~/workbook/hardware/UART/push_test1$ ./push_test
arg1: abcd
arg2: 123
arg3: .name = zhangsan, .age = 15, .score = A, .id = 3
book@www.100ask.org:~/workbook/hardware/UART/push_test1$
为什么啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊??????????????????
4.最终的运行结果为
book@www.100ask.org:~/workbook/hardware/UART/push_test1$ ./push_test
arg1: abcd
arg2: 123
arg3: .name = zhangsan, .age = 15, .score = A, .id = 3
arg4: c = W
arg5: d = 3.140000
book@www.100ask.org:~/workbook/hardware/UART/push_test1$
*/
2.//========================================================================================================
/*2018-05-25
File: push_test1
功能:
*/
#include <stdio.h>
#include <stdarg.h>
struct person
{
char * name;
int age;
char score;
int id;
};
/*参考标准函数:int printf(const char * format, ...)
*依据:x86平台,函数调用时参数的传递是使用堆栈来实现的
*目的:将所有传入的参数全部打印出来
*/
int push_test(const char * format, ...)
{
//volatile char *p = (char *)&format;
//char *p = &format;
int i;
struct person per;
char c;
double d;
va_list p;
printf("arg1: %s\n", format);
//printf("&format = %p\n", p);
//p = p + sizeof(char *);
va_start(p, format);
//i = *((int *)p);
//p = p + sizeof(int);
i = va_arg(p, int);
printf("arg2: %d\n", i);
//printf("&i = %p, p = %p\n", &i, p);
//per = *((struct person*) p);
//p = p + sizeof(struct person);
per = va_arg(p, struct person);
printf("arg3: .name = %s, .age = %d, .score = %c, .id = %d\n", per.name, per.age, per.score, per.id);
//printf("&per = %p, p = %p\n", &per, p);
//c = *((char *)p);
//p = p + ((sizeof(char) + 3) & (~3));
c = va_arg(p, int);
printf("arg4: c = %c\n", c);
//d = *((double *)p);
//p = p + (sizeof(double) & (~3));
d = va_arg(p, double);
printf("arg5: d = %lf\n", d);
va_end(p);
return 0;
}
int main(void)
{
struct person per = {"zhangsan", 15, 'A', 003};
push_test("abcd", 123, per, 'W', 3.14);
return 0;
}
/*
当 //volatile char *p = (char *)&format; 未修改为:
va_list p; 时,编译链接的结果如下:
In file included from push_test.c:7:0:
push_test.c: In function ‘push_test’:
push_test.c:35:11: warning: passing argument 1 of ‘__builtin_va_start’ from incompatible pointer type [-Wincompatible-pointer-types]
va_start(p, format);
^
push_test.c:35:11: note: expected ‘char **’ but argument is of type ‘volatile char **’
push_test.c:62:9: warning: passing argument 1 of ‘__builtin_va_end’ from incompatible pointer type [-Wincompatible-pointer-types]
va_end(p);
^
push_test.c:62:9: note: expected ‘char **’ but argument is of type ‘volatile char **’push_test。c:35:11:注意:预期“char **”,但参数是“volatile char **”
push_test.c:39:16: error: first argument to ‘va_arg’ not of type ‘va_list’
i = va_arg(p, int);
^
push_test.c:46:18: error: first argument to ‘va_arg’ not of type ‘va_list’
per = va_arg(p, struct person);
^
push_test.c:53:16: error: first argument to ‘va_arg’ not of type ‘va_list’
c = va_arg(p, char);
^
push_test.c:59:16: error: first argument to ‘va_arg’ not of type ‘va_list’
d = va_arg(p, double);
^
//--------------------------最终的输出结果为:--------------------------//
book@www.100ask.org:~/workbook/hardware/UART/push_test2$
book@www.100ask.org:~/workbook/hardware/UART/push_test2$ ./push_test
arg1: abcd
arg2: 123
arg3: .name = zhangsan, .age = 15, .score = A, .id = 3
arg4: c = W
arg5: d = 3.140000
book@www.100ask.org:~/workbook/hardware/UART/push_test2$
*/
3.//==============================================================================================
/*2018-05-25
File: push_test2
功能:
*/
#include <stdio.h>
//#include <stdarg.h>
typedef char * va_list; //错误写法:typedef (char *) va_list; error: expected identifier or ‘(’ before ‘char’typedef (char *) va_list;
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1)) //错误:sizeof写成siezeof
#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v))
//#define va_arg(ap, t) (*(t *)(ap += _INTSIZEOF(t) - _INTSIZEOF(t))) //错误:*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))写成
*(t *)(ap += _INTSIZEOF(t) - _INTSIZEOF(t))
#define va_arg(ap, t) (*(t *)(ap += _INTSIZEOF(t) - _INTSIZEOF(t)))
#define va_end(ap) (ap = (va_list)0)
//typedef char * va_list;
//#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
//#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v))
//#define va_arg(ap, t) (*(t *)(ap += _INTSIZEOF(t), ap - _INTSIZEOF(t)))
//#define va_end(ap) (ap = (va_list)0)
struct person
{
char * name;
int age;
char score;
int id;
};
/*参考标准函数:int printf(const char * format, ...)
*依据:x86平台,函数调用时参数的传递是使用堆栈来实现的
*目的:将所有传入的参数全部打印出来
*/
int push_test(const char * format, ...)
{
//volatile char *p = (char *)&format;
//char *p = &format;
int i;
struct person per;
char c;
double d;
//volatile char *p = (char *)&format;
va_list p;
printf("arg1: %s\n", format);
//printf("&format = %p\n", p);
//p = p + sizeof(char *);
va_start(p, format);
//i = *((int *)p);
//p = p + sizeof(int);
i = va_arg(p, int);
printf("arg2: %d\n", i);
//printf("&i = %p, p = %p\n", &i, p);
//per = *((struct person*) p);
//p = p + sizeof(struct person);
per = va_arg(p, struct person);
printf("arg3: .name = %s, .age = %d, .score = %c, .id = %d\n", per.name, per.age, per.score, per.id);
//printf("&per = %p, p = %p\n", &per, p);
//c = *((char *)p);
//p = p + ((sizeof(char) + 3) & (~3));
c = va_arg(p, int);
printf("arg4: c = %c\n", c);
//d = *((double *)p);
//p = p + (sizeof(double) & (~3));
d = va_arg(p, double);
printf("arg5: d = %lf\n", d);
va_end(p);
return 0;
}
int main(void)
{
struct person per = {"zhangsan", 15, 'A', 003};
push_test("abcd", 123, per, 'W', 3.14);
return 0;
}
/*
1.最终的运行结果为
book@www.100ask.org:~/workbook/hardware/UART/push_test1$ ./push_test
arg1: abcd
arg2: 123
arg3: .name = zhangsan, .age = 15, .score = A, .id = 3
arg4: c = W
arg5: d = 3.140000
book@www.100ask.org:~/workbook/hardware/UART/push_test1$
*/