原创C语⾔⾼级⽤法-学习笔记
#是将其后的变量直接转换为字符串
void WriteLog(arg)
{
printf("%s=%d",#arg,arg)
}
1.##的作⽤
##的作⽤是连接两个变量
#define combine_converse_str(x,y) x##y
int Err;
int Num;
printf("%s",combine_converse_str(Err,Num));
结果为:ErrNum
再如:
int a=1;
int b=2;
c语言char的用法int ab=3;
printf("%d",a##b);
结果为: 3
后⾯那句相当于printf("%d",ab);
2.do{ }while(0)作⽤
1,空的宏定义避免warning:
#define foo() do{}while(0)
2,存在⼀个独⽴的block,可以⽤来进⾏变量定义,进⾏⽐较复杂的实现。
3,⽤在宏定义上并且当宏定义需要定义成多条语句的组合时,可以保证这⼏条语句是⼀个整体的,并且可以消除使⽤这个宏定义后添加";"所带来的报错,例如:
#define aaa(x,y) \
do{ \
int a=0; \
int b=0; \
函数1(x); \
函数2(y); \
}while(0)
调⽤aaa(x,y); 时不会报错并且如果使⽤:
if (m)
aaa(1,2);
else
aaa(3,4);
时运⾏也不会使某些语句没有被运⾏到。
3.数组名的使⽤
A.数组名作为函数参数:数组名⽤在某个函数A的参数中时,处于函数传递效率原因,会被强制转换成了指针,此后在函数A内就完全是⼀个值等于对应数组⾸地址的指针变量,可⾃加⾃减等
注意!只有在作为函数参数的情况下才会将数组名强制转换成指针,其他的都不会转换。
另:数组名作为函数参数传递时,函数声明的写法有多种
int aaa(char x[])
int aaa(char x[1])
int aaa(char x[100])
int aaa(char *x)
作为函数参数时的参数声明也和普通的数组定义⼀样要合法,⽐如不能 int aaa(char x[0]),因为定义⼀个数组也不能⽤ char x[0]来定义,编译器在检查参数的声明合法后,如果发现参数是数组,就会强制转换成指针,所以int aaa(char x[1])和int aaa(char x[100])的结果是⼀样的。
B.数组名⽤在sizeof上:结果返回的是整个数组所占空间的⼤⼩,⽽不是⼀个指针的长度
C.数组名与&和*:a与&a与&a[0]的值都相等,a是数组名,&a是整个数组地址,&a[0]是数组⾸元素的地址,他们都相等int a[5]={1,2,3,4,5};
printf("a=%x\n",a);
printf("&a=%x\n",&a);
printf("*&a=%x\n",*&a);
printf("&a[0]=%x\n",&a[0]);
printf("*&a[0]=%x\n",*&a[0]);
printf("*(&a[0])=%x\n",*(&a[0]));
printf("*((int *)(&a))=%x\n",*((int *)(&a)));
printf("*(*(&a))=%x\n",*(*(&a)));
结果:
a=12ff34
&a=12ff34
*&a=12ff34 ---*与&消掉,*&a=a=0x12ff34
&a[0]=12ff34
*&a[0]=1 ---*与&消掉,*&a[0]=a[0]=1
*(&a[0])=1 ---*与&消掉,*(&a[0])=*&a[0]=a[0]=1
*((int *)(&a))=1 ---*与&之间有个强制类型转换(int *),⽆法直接消掉,所以按照括号次序来运算(int *)(&a)=0x12ff34, *((int *) (&a))=*(0x12ff34)=1 *(*(&a))=1 ---*与&消掉,*(*(&a))=*a=1
D.指针数组:
定义:基类型*数组名[]
使⽤:像普通的数组⼀样使⽤,数组名代表⾸地址,数组名[0]表⽰第⼀个元素的内容,以此类推。
常见的是字符串数组,例如:
char *Names[]=
{
Bill,
Sam,
Jim
};
实际内存中保存的就是
即⾸地址0x12ff0c{0x00423018,0x0042f2f4,0042201c},其中0x00423018地址所保存的就是”Bill”,所以数组名
Name=0x12ff0c, &Name=0x12ff0c,*Name=0x00423018,**Name=0x42
printf("Name=%x\n",Name);
printf("&Name=%x\n",&Name);
printf("*&Name=%x\n",*&Name);
printf("&Name[0]=%x\n",&Name[0]);
printf("*Name=%x\n",*Name);
printf("**Name=%x\n",**Name);
printf("Name[0]=%x\n",Name[0]);
printf("*Name[0]=%x\n",*Name[0]);
printf("*&Name[0]=%x\n",*&Name[0]);
printf("*(&Name[0])=%x\n",*(&Name[0]));
printf("(*((int *)(&Name)))=%x\n",(*((int *)(&Name))));
printf("(*(*(&Name)))=%x\n",(*(*(&Name))));
结果是
Name=&Name=*&Name=&Name[0]=0x12ff0c
*Name=Name[0]=*&Name[0]=*(&Name[0])=(*((int
*)(&Name)))=(*(*(&Name)))=0x00423018
**Name=*Name[0]=0x42
注意!指针是⼀级,数组是⼜⼀级,所以指针数组是⼆级指针,定义对应的指针变量要⽤⼆级指针,⽐如 int **p=Name; 不能直接⽤int *p=Name
4.常量的定义和指针常量的定义及使⽤:
1.常量的定义:
const int a=10; 也可以写成 int const a=10; 针常量的定义和使⽤:
有3种定义: const int *pi; 和 int const *pi; 以及 int * const pi;
1)前两种情况⼀样的,没有区别。
1) 如果const 修饰在*pi前(前2种情况)则不能改的是*pi(即不能类似这样:*pi=50;赋值)⽽不是指pi.
2) 如果const 是直接写在pi前(后⼀种情况)则pi不能改(即不能类似这样:pi=&i;赋值)。
5.函数参数传递的4种类型:
1.值传递
void Exchg1(int x, int y)
{
int tmp;
tmp = x;
x = y;
y = tmp;
printf("x = %d, y = %d\n", x, y);
}
main()
{
int a = 4,b = 6;
Exchg1(a, b);
printf("a = %d, b = %d\n", a, b);
return(0);
}
2.地址传递
void Exchg2(int *px, int *py)
{
int tmp = *px;
*px = *py;
*py = tmp;
printf("*px = %d, *py = %d.\n", *px, *py);
}
main()
{
int a = 4;
int b = 6;
Exchg2(&a, &b);
printf("a = %d, b = %d.\n", a, b);
return(0);
}
3.引⽤传递
void Exchg3(int &x, int &y)
{
int tmp = x;
x = y;
y = tmp;
printf("x = %d,y = %d\n", x, y);
}
main()
{
int a = 4;
int b = 6;
Exchg3(a, b);
printf("a = %d, b = %d\n", a, b);
return(0);
}
4.变长参数传递:使⽤省略号…指定参数表
使⽤的宏及其定义(x86中):
#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end
typedef char * va_list;
#define _ADDRESSOF(v) ( &(v) )
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define _crt_va_start(ap,v) ( ap =
(va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) #define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define _crt_va_end(ap) ( ap = (va_list)0 )
实例:
#include ""
#include ""
#include ""
#include ""
/*⾄少需要⼀个确定的参数,注意括号内的省略号*/
int demo(char *fmt, ...)
{
va_list argp;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。