C语言笔记

  •  当函数前面加上static时,表示该函数仅在本文件里被调用,不会与其它文件相同函数发生冲突
  •  调用库的头文件使用<>,调用自己创建的头文件使用""

memset

memset对于强制转换类型不同的指针,赋值是有误的

例如:

#include "stdio.h" 
#include "string.h"
int main()
{
unsigned char s[4]={0x12,0x34,0x56,0x12};

unsigned short *p16=(unsigned short *)s;


memset(p16,0x1234,2);

for(int i=0;i<2;i++)
printf("0x%x ",*p16++); 

return 0;
}

输出结果:

因为s[4]转为16位后,数据为:0x3412  0x1256,而执行 memset(p16,0x1234,2)代码时,

由于*p16的内容实际是8位的,所以只能放入0x34低8位,放入0x12高8位时便出错返回了.

所以*p16打印的结果为: 0x3434 0x1256

改为以下代码,不使用memset便可以实现:

#include "stdio.h" 
#include "string.h"
int main()
{
    unsigned char s[4]={0x12,0x34,0x56,0x12};
     
    unsigned short *p16=(unsigned short *)s;
    
    for(int i=0;i<2;i++) 
     p16[i]=0x1234; 
      
    for(int i=0;i<2;i++)
    printf("0x%x  ",*p16++); 
     
    return 0;
} 

  

struct

struct internal{
  int i;
  int j;
}inter;                //定义一个 struct internal inter变量

  

typedef

typedef  struct LNode LNode;    //通过LNode别名代替struct LNode

typedef  struct LNode *LinkList;   //表示LinkList指向struct LNode,
//比如LinkList p ; 等价于: struct LNode *p;

对于指针typedef而言, 其实和指针结构体很像

例如:

#include "stdio.h"

typedef struct internal{
int i;
int j;
}Inter, *Pint;      //Inter类型等价于struct internal  ,  Point 等价于 struct internal*

int main()
{
inter buff[100]={
{1,2},{2,3},{3,4}
}; 

Pint p=buff; //等价于   struct internal *p=buff;

for(int i=0;i<3;i++)
{
p->i++;
p->j++;    
p++;
} 

for(int i=0;i<3;i++)
printf("%d %d
",buff[i].i,buff[i].j);
printf("%d
",p-buff); 
}

 输出结果:

 

#define

我们平时编译代码时,首先会进入预处理器,预处理器会去检查代码规范,以及将define宏替代为文本.

所以define也可以这样使用:

#include <stdio.h>
  
#define SWAP(t, a, b)    
do                       
{                        
    t c = a;             
    a = b;               
    b = c;               
}while(0)

int main( )
{
    int a=0,b=1;
    
    SWAP(int,a,b);
    
    printf("%d,%d
",a,b); 
    
    return 0;
}

运行打印:

1,0

在我们测试产品时,需要串口打印,产品成功后,又要取消串口打印,不妨通过define宏来处理,例如:

#if   defined(DEBUG_U3)       
#define   debug    u3_printf

#elif     defined(DEBUG_U2)       
#define   debug    u2_printf

#elif  defined(DEBUG_U1)  
#define   debug    u1_printf

#else
#define   debug(...)                //表示预处理器遇到debug(...)时,会省略掉该语句,从而不打印输出

当判断一个宏是否存在时,尽量使用:

#if defined(CONFIG_XXX)

         //... ...
 
#endif

不要使用 #ifdef CONFIG_XXX

当判断宏等于多少时:

#if ( CONFIG_LCD_HIDE_OFF == 1 )//SIZE_FONT_32X32
   u8 MaxFont =  SIZE_FONT_100X100;
#else
   u8 MaxFont =  SIZE_FONT_32X32; 
#endif 

最小二乘法拟合曲线公式

利用最小二乘法将一系列的XY坐标数据拟合为二次曲线

用EXCEL显示出的拟合曲线公式,和通过公式计算出来的公式对比:

代码如下:

#define N 1e-13
/*
************************************************************************** * count: 表示XY坐标点数 * * a b c: y=ax*x+bx+c; * *******************************************************************************/ void analyzeCurve(double *x,double *y,double *a,double*b,double *c,int count) { double m1,m2,m3,z1,z2,z3; double sumx=0,sumx2=0,sumx3=0,sumx4=0,sumy=0,sumxy=0,sumx2y=0; int i; *a=*b=*c=0; z1=z2=z3=999; for(i=0;i<count;i++) { sumx+=x[i];sumy+=y[i]; sumx2+=pow (x[i],2); sumxy+=x[i]*y[i]; sumx3+=pow(x[i],3); sumx2y+=pow(x[i],2)*y[i]; sumx4+=pow(x[i],4); } while((z1>N)||(z2>N)||(z3>N)) { m1=*a; *a=(sumx2y-sumx3*(*b)-sumx2*(*c))/sumx4; z1=(*a-m1)*(*a-m1); m2=*b; *b=(sumxy-sumx*(*c)-sumx3*(*a))/sumx2; z2=(*b-m2)*(*b-m2); m3=*c; *c=(sumy-sumx2*(*a)-sumx*(*b))/count; z3=(*c-m3)*(*c-m3); } printf (" y=%9.6fx*x+%9.6fx+%9.6f",*a,*b,*c); } int main() { double x[21]={0.00,20,40,60,80}; double y[21]={0.00,23,60,77.69,79.64}; double a,b,c ; analyzeCurve(x,y,&a,&b,&c,5); return 0; }

指针

在指针中*是取内容,&是取地址

(在结构体中时:变量结构体用".",指针结构体用"->",比如p指针:    p->val   <--->  (*p).val   )

通常有两种的表示:

1. 通过指针向指向的地址内容赋值

*p=a; //将p指向的地址里赋a值

注意:若a和p定义的变量类型不一样时,需要用到强制转换才行.

当指针指向的地址内容是一个变量时,

实例如下:

int main()
{
int   *p=0x12345678;                     //定义一个int型指针*p,p=0x12345678这个地址。
char    a='0';                   //定义一个char型变量b
*p=(int)a;                 //*p等于a(0x12345678这个地址的内容等于a变量的值)          
}

  

当指针指向的地址内容是另一个指针指向的地址内容时,

实例如下:

int main()
{
int   *p=0x12345678;             //定义一个int型指针*p,p=0x12345678这个地址。
char    b='0';                   //定义一个char型变量b
char *a=&b;                //定义一个char型指针*a,a=&b,表示a指针的地址等于b的地址。
*p=*(int *)a;          //首先是先执行(int *)强制转换为int型指针,然后*p等于*a(0x12345678地址的内容等于'0'这个变量)          

}

2. 指针指向其它的地址

p=&a; //将p的地址 指向a的地址

   它和"int a=0,*p=&a;"一个意思,这里的*只是代表定义一个指针(不是指向地址的内容),然后指针p=&a;

实例如下:

int main()
{
int a=0,*p; //定义一个int型指针p,p等于0x12345678这个地址。
p=&a; //p等于a的地址,则*p=0
}

3.指针地址与数值相加

   指针地址与数值相加和数值与数值相加不一样,

char型指针:0X3000+1=0X3001           (因为1个地址保存8位数据,而char是8位.)

short型指针:0X3000+1=0X3002          (16位)

int、long型指针:0X3000+1=0X3004    (32位)

long long型指针:0X3000+1=0X3008   (64位)

 变量与变量相加,实例如下:

#include "stdio.h"

 #define tag_next(t)    ((int *)((unsigned long)(t) + 1))   
int main()
{
    int i=3,*t=&i;
    printf("  %x,%d
", t,*t);    
    t=tag_next(t);         //t=  *(t+1)
    printf("  %x,%d
", t,*t);    
}

这里的tag_next(t): 将t地址强制转换为u32变量,与另一个变量1相加

代码输出如下:

 也就是t=0X28ff18+1=0x28ff19

  int型指针地址与变量相加,实例如下:

#include "stdio.h"

 #define tag_next(t)    ((int *)((unsigned int*)(t) + 1))
int main()
{
    int i=3,*t=&i;
    printf("  %x,%d
", t,*t);
    t=tag_next(t);               //t=*((unsigned long *)t +1)
    printf("  %x,%d
", t,*t);    
}

这里的tag_next(t): 将t地址强制转换为u32*指针,然后这个指针地址与另一个变量1相加

代码输出如下:

也就是t=0X28ff18+1=0x28ff18+4=0x28ff1c

原文地址:https://www.cnblogs.com/lifexy/p/7183495.html