Ⅰ c语言 可变参数宏的问题
这个问题可以这样考虑:
你在write_log()函数里调用了vfprintf()函数,其实这个vfprintf()就是一个可以接受你从上层函数传下来的可变参数串的函数。
你现在要在
log_info()
函数下调用
write_log()
函数,并想把可变参数串传给它,你只要参考
vfprintf()
的函数定义来定义
write_log()
函数就可以。
c语言中
vfprintf()
函数的定义是:
int
vfprintf(file
*stream,
const
char
*format,
va_list
ap);
不知你是否能受到启发。
Ⅱ 简单的C语言问题
分配aSize个int大小的空间。一个int是4字节,结果是分配了aSize*4字节的内存空间。
Ⅲ C语言 其中typedef char (*AP)[5];自定义的类型是什么APreturn的是什么
AP是指向长度为5的数组的指针,可简单讲是属于二级指针,return (AP)p+1是语法上看起来别扭的用法,p不是二级指针,但含义被强制转成了每5个字符一组的二级数组,并且返回第二个子组,也就是说p与a一样,指向数组中最前面的'F',但返回值是指向以第5个字符‘S'开头的子组的指针,也还是二级指针(而且函数defy还把p数组的3个'\0'都改成了’A',也就是把所有子组全都用'A'连在一起了),puts(defy(a)[1]+2)在返回值defy(a)的基础上defy(a)[1]又是取第二个子组,即指向的是字符'L'开头的子组,但这回是踏踏实实的了,得到的是char[5]这样的普通含义的字符串指针,简单说defy(a)[1]就指向'L'了,后面再+2是跳过2个字符,改指向'O‘了,puts输出从'O'开始的字符串,注意因为defy做的改写,“O”和后面的“LAMP”被’A‘连在一起了。 整个很别扭的根本原因是char a[] = 这里,干脆把它改成char a[][5] = 那么是不是对LZ理解有帮助呢
Ⅳ c语言中*ap=100,中是让指针变量指向的地址为100的存储单元还是怎样
#include
<stdio.h>
int
main(void)
{
int
num;
int
*
ap;
ap
=
#
/*
将int指针指向num变量的地址
*/
*ap
=
100;
/*
将int指针所指变量数值赋值为100
*/
/*
ap
=
0x401000;
*/
/*
地址赋值,
但不推荐这么做
因为可能会出现内存读取错误
且本身编译器也会提示:
warning:
assignment
makes
pointer
from
integer
without
a
cast
*/
printf("num
addr.:
%p,
num
val.:
%d\n",
&num,
num);
printf("pointer
addr.:
%p,
pointer
val.:
%d\n",
ap,
*ap);
/*
'&'
为取址运算符
*/
return
0;
}
输出参考:
num
addr.:
0022ff74,
num
val.:
100
pointer
addr.:
0022ff74,
pointer
val.:
100
Ⅳ 代码“va_start(ap,fmt)”是什么意思
VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h>头文件下。
Ⅵ C语言的变元参数
这个例子中参数们被放置在一个32位的数组中
参数int a是第一个参数,通过他的地址依次+32位即代码中的ap+=4就可以找到其他参数地址并转换成相应的类型
这种方式不灵活,不同的系统情况可能不同,所以最好用已经定义好的宏
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
void va_start( va_list arg_ptr );
void va_start( va_list arg_ptr, prev_param );
你搜一下这些应该有不少介绍的。
Ⅶ 今天学习C语言可变参数,学习到如下C代码,有些地方不太懂,想请教大侠帮忙解释不好意思,没财富了。。
ap = ((char*)&fmt) + sizeof(fmt); 这里char* 是强制转换
因为参数定义为const char * fmt fmt是一个指向字符串常量的指针 内容是不可以修改的
而 char * ap char类型的指针 这句话的意思就是将 指向字符串常量的指针的地址赋给 字符串型指针 ap 类型不一样需要强转
地址 内容
memory 0x1234 %d %d %s\n
fmt存储的内容
ap -> 存储fmt的地址
printf("%s\n", *((char**)ap)); 这里char**的作用就是获得 指针里存放的指针
内容“%d %d %s\n” 因为ap是char* 类型 但ap里的值是 char**类型 (是指针的指针根据上面的分析可知)所以要强制转换一下
Ⅷ c语言可以条用AP那些函数I
当然可以!!!你只需在源文件头部加入下面这条语句:
#include<windows.h>
即可调用绝大多数API,其他一些极少数的API函数还需包含另一些头文件...总之,在VC环境下,只要包含必需的头文件,就可以调用所有微软提供的有名字的WindowsAPI函数...
另外,建议你查阅微软提供的技术文档 MSDN 上面有微软提供的所有有名子的API...
Ⅸ C语言中可变参数宏的va_start(ap, v)
我把你的提问分为3个问题:
1、为什么printf("%s", ap);输出不了?
2、va_start(ap, v)的定义中为什么使用二级指针?
3、va_arg(ap,t) 的定义中为什么用*(t *),它的作用是?
在解释之前,先确认一个小问题:
在C语言中,指针这种类型的大小实际上一样的,我的意思是说无论是char *a,还是int *a,或者是char **a,a这个指针变量所占用的内存空间是一样的(都是sizeof(a),究竟是等于4,还是8取决于CPU的位数)
先回答第一个问题:
你应该知道va_list的定义:typedef char * va_list;
也就是说ap可以理解为一个char *类型的变量,va_start(ap,c)这个执行之后,ap确实指向了可变参数列表中的第一个参数,注意【是ap这个指针指向了第一个参数】,而如果你的第一个参数是一个字符串(C语言中也就意味着是一个char*的变量),这样的话,ap这个指针就指向了一个char*类型的指针变量,【指向指针的指针变量是二级指针变量】这个我就不用多说了吧,所以printf("%s", ap);是无法输出的,而修改为printf("%s", *(char **)ap);应该就可以输出了!
然后是第二个问题:
这里先说一下函数调用过程中参数传递的问题:
【 函数参数是以数据结构:栈的形式存取,从右至左入栈。
首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址,举个例子如下:
void func(int x, char *y, char z);
那么,调用函数的时候,实参 char z 先进栈,然后是 char *y,最后是 int x,因此在内存中变量的存放次序是 x->y->z,因此,从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,则总可以顺藤摸瓜找到其他的输入变量。】
注意,x,y,z这几个变量是存放到堆栈中的,所以我们需要获得的不是y这个变量本身,而是它在堆栈中的地址,而ap这个指针变量就是保存着堆栈中函数入参的地址的,所以在va_start(ap, v)的定义中要使用&v,而不管v变量本身是什么类型的(哪怕v是一个指针变量,甚至是二级指针)&v都表示一个地址,所以可以强制转换为va_list类型(也就是char *)。
第三个问题:
要睡觉了,先自己想吧,如果还不明白,就留言追问吧。
Ⅹ C语言中的左结合性是什么
意思是:从表达式右边开始执行;只有同优先级的运算符才具有结合性“自左至右”或者“自右自左”一说。
有些运算符的优先级是错误的。
“当按照常规方式使用时,可能引起误会的任何运算符”就是存在错误优先级的运算符。
.的优先级高于*。->操作符用于消除这个问题。
*p.f变成了*(p.f)而不是(*p).f
[]高于*,于是int
*ap[]中的ap变成了元素为int指针的数组。
函数()高于*,因此,int
*fp()不再是函数指针了,而是一个函数,返回int
*。
逗号运算符在所有运算符中优先级最低,所以,i
=
1,
2就成了(i
=
1),
2而不是i
=
(1,
2)。
逗号运算符的值是最右边操作数的值,逗号运算符结合性从左至右,因此又称为顺序求值运算符。
在表达式中如果有布尔操作、算术运算、位操作等混合计算,始终应该在适当的地方加上括号。
x
=
f()
+
g()
*
h();
乘法先于加法执行,但是g()和h()的调用可能以任何顺序出现。
同样,f()可能在乘法之前调用,也可能在乘法之后调用。
优先级和结合性规则告诉你哪些符号组成一个意群,大部分这样的意群内部如何进行计算的次序是未定义的。
有些操作符,如&&和||等,其操作数的计算顺序是确定的,它们使用短路原则。
C语言中记住两个优先级就够了:乘法和除法先于加法和减法,在涉及其他操作符时一律加上括号。
结合性用于在几个操作符具有相同的优先级时确定先执行哪一个。
每个操作符拥有某一级别的优先级,同时也拥有左结合性或者右结合性。所有的赋值符(包括复合赋值符)都具有右结合性(从右到左执行),因此可以使用连等的赋值形式。
唯一的三目运算符?:也是具有右结合性的。
所有优先级相同的操作符,它们的结合性也相同,这是必须如此的。在函数调用中,各个参数的计算顺序是不确定的。