用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

德良    -  云代码空间

—— Coding是一种生活!

c&c++学习笔记

2014-12-06|1852阅||

摘要:c&c++学习笔记

C/C++部分

1.编译

gcc -c xx.c形成一个xx.o文件

 

2.连接

gcc xx.o形成a.out可执行文件(gcc xx.o -oxxx制定生成xxx.o文件)

 

注释:include头文件 ls /usr/include

       vi 中显示行数设置  set nu

       C语言注释/*  */C++下的注释//

       续行符"\":如#include \

     <stdio.h>,即下一行和上一行为一个语句;

       C语言结尾一般留出一个空行;

       '0'--'9'ASCLL码:48--57

      数字-->字符:+'0';字符-->数字:-'0';

 

3.输出格式

%i/%d:int

%hd/%ld:short int/long int

%u:unsigned int

%f/%lf:float/double

%g:float/double去掉了尾随的0

%x/%o:十六进制/八进制

%p:地址

%c:字符

%s:字符串

 

4.变量

变量的类型:字母、数字、下划线(数字不能放在前面)

如:int a;正确

    int 5a;错误

 

5.类型转换

强制类型转换:int n=(int)3.14159;(类型转换,只是值的转换,变量类型不会改变)

注释:如何看汇编gcc -S xx.c/cpp;

      定义宏预处理#define name "Jack"(在程序中用name替换Jack),查看宏:gcc -E xx.c/cpp(注意:宏的后面没有";"分号);

          定义一个常量,必须一并初始化,否则在后面就不能给之赋值,因为常量不能改变它的值,如 const int p=2;

 

6.运算符

位运算符:与   1&1->1

          | 或   1|0->1

     ^异或  1^1->0   1^0->1(作用,可以把某个或几个反转)

 

注释:逗号运算符做运算,以第二个作为实际值,如:

  printf("%d\n",(a=123,b=456));输出的值为456;

         运算符右结合顺序:如printf("%d %d %d\n",i++,i++,i++);

  输出从右向左,比如i初始值为0,则输出结果2,1,0

 

7.输入输出

------清除输入缓冲区剩余字符:scanf("%*[^\n]%*c");

 

8.循环

对于continuebreak,用于循环之中,continue是跳过循环中continue后面的语句,继续执行循环中前面的语句;break是直接跳出循环体;

 

9.枚举

#include<stdio.h>

enum bool{true,false};

//大括号里面的是枚举常量(字面量),它的值默认第一个是0,后面的依次加1

//比如这里true=0,false=1;可以指定值,比如true=1,false=0

//枚举里面的字面量必须是整型

enum mode{};

void main()

{

     printf("%d\n",true);

}

 

10.类型起别名(声明一个新的类型名)

typedef int T;

T a;

T b;//相当于int b;

注意:typedef只是对已存在的类型增加一个类型名,而并没有创造一个新的类型;

===================================

<给什么起别名,typedefint起别名T>

===================================

 

11.数组

数组名表示第一个元素的地址;

数组名本身不是一个变量,不占有存储空间;

 

字符数组:

 

1.

#include<stdio.h>

void main()

{

     char m[4]={'a','b','c','d'};//m是个字符数组,但不是字符串(字符串有结尾标志"\0")

}

 

2.

 

字符数组初始化(只可以初始化,不可以赋值):

char a[100]="hello world!";

 

不能a="hello world1",但可以strcpy(a,"hello world!");

 

#include<stdio.h>

#include<string.h>

void main()

{

char a[100]="Hello world!";

puts(a);

strcpy(a,"Good afternoon ");

puts(a);

strcat(a,"friends!");

puts(a);

printf("%s\n",strchr(a,'f'));//a中查找f,并输出其后的字符串

printf("%s\n",strrchr(a,'f'));//从右向左查找f,并输出从右向左查找的字符串

}

 

    

注释:sizeof()只关心类型,不关心内容;strlen()测试字符串长度;

      int a[10];n那么a的类型是int[5];

         字符串的输出,找到他的地址(第一个元素的地址),然后输出,直到'\0'结束;

 

11.结构

char a[1][2]={{"",""},{"",""}};

 

对齐和补齐问题(存放的起始地址是自身的倍数开始):

struct Person{

char name;//1

int age;//跳过3个字节,即从第四个地址开始

int id;//4

char sex;//1,但是补齐3个,总共占4个字节

}p;

 

所以sizeofp=16;(一般是以int4为单位);

 

struct Goods{

char name[17];//0开始到17,共占17字节

char special;//171的倍数,故占18这个地址,占1个字节

short sale;//18开始,182的倍数,占两个字节

double price;//20开始,占8个字节

int num;//28开始,284的倍数,故占4个字节

}g;

所以sizeof(g)=32;

 

 

12.联合(union

联合即共用体,占用同一块内存,对一个成员进行操作,则会影响其他成员;

定义和使用类似结构体;

 

13.函数

防止回车换行符影响读入操作,那么在scanf前加一个空格符,例如:

scanf(" %c",&name);

 

注释:如何清除缓冲区

void clear()

{

scanf("%*[^\n]");

scanf("%*c");

}

==============================

如何将数字0--9转化为汉字:

char nem[10][5]={"""""","""",""""""""""};

printf("%s",num[c-'0']);

 

 

14.变量修饰

 

对全局变量/函数加static,表示只能在本文件中使用。

 

全局变量和静态局部变量自动初始化为零;

 

将一个变量申明放在寄存器(register)中,就不要去取地址;

 

C中函数参数和类型是空的,表示参数不定,即也可以任意传参数;

如果加了void,则表示不接受任何参数,如void fun(void),即不传;

 

 

注释:如何让一个数加倍,左移即可,如a=11a<<=1,a=22

         栈用来保存函数的返回地址;

 

 

15.可变长参数列表

 

例:不定长参数求最大值:

#include<stdio.h>

#include<stdarg.h>

int max(int cnt,...)//可变长参数列表

{

va_list v;//v保存可变长参数表,va_list是一个类型

va_start(v,cnt);//开始一个可变长形参列表,cnt开始,v保存cnt之后参数

int i;

int maxvalue=va_arg(v,int);//取元素,第二个参数是要取参数的类型

for(i=1;i<cnt;i++)

{

int data=va_arg(v,int);

if(data>maxvalue)

maxvalue=data;

}

va_end(v);//释放可变长参数表v

return maxvalue;

}

void main()

{

printf("%d\n",max(2,36,56));

}

 

 

16.宏(macro

1

#include<stdio.h>

#define H "Hello\n"

#ifndef H

#define H "你好!\n"

#else

#define __H H

#undef H

#define H "**\n"

#endif

void man()

{

H;

}

 

 

2

#ifndef VX 

#define VX 1

int x=2;

#endif

 

3:(宏可以带参数--宏函数)

#include<stdio.h>

#define SWAP(T,x,y) {T t=x;x=y;y=t;}

void main()

{

int a=9,b=10;

SWAP(int,a,b);

}

 

4:(带参数的宏总要用括号括起来)

#define APEA(r) PI*(r)*(r)

 

 

c中内置的宏:

__FILE__  "predef.c"

 

__LINE__  表示当前的行

 

__DATE__  表示当前日期

 

__TIME__  表示当前时间

 

 

17.指针

1.指针,其实是两个变量(地址和保存地址的变量)

int *p=NULL;p是一个指针,指向int型的指针;

 

2.野指针:

int *p;

printf("p=%p\n",p);//这里p就是野指针

(尽量避免野指针,初始化int *p=NULL;)

 

注释:函数中返回局部变量的地址

例:char *fun()

    {

char a='&';

return &a;//不要返回普通局部变量的地址;

     }

    int main()

    {

char *p=NULL:

p=fun();//这里函数fun()返回局部变量之后,

  局部变量出了函数之后会消失,此时返回的指针已经悬空,

  即指向一个可能已经释放的地方;

     }

 

3.定义指针变量:

int *p=NULL,q=NULL;//此处并不能成功定义q

int *p=NULL,*q=NULL;//正确


4.内存中交换地址并不能交换元素值(相当于左右分别站了一个男的和一个女的,

用左右手指分别指向他们,现在改变手指指向

<类似改变指针变量指向>,但他们人本身并没有改变<即值没有改变>)

 

5.C中是值传递;


6.指针变量永远占4字节:

如:char *p="Hello";sizeof(p)=4;


7.形参里面的数组名实际是指针:

#include<stdio.h>

print(int m[],int n)

{

printf("sizeof(m)=%d\n",sizeof(m));

}

void main()

{

int a[3]={1,2,3};

print(a,3);

}

 

结果是:4;因为print(int m[],int n),其实就是print(int *m,int n);


8.const对指针的使用(见附录:const对指针操作实例);

 

9.区分:

int *a[5]//a是一个数组,里面有5个元素,每个元素是int*-----a不是指针,只是一个数组名而已,指针数组;

int *a(double)//a是一个函数,有一个形参类型是double,返回int*;

int(*a)[5]//a是一个指针,指向一个含有5个元素的int型的数组------a指向数组的指针;


10.函数指针(指向函数的指针)

如:int(*p)(double)

================================================

注释:问一个类型,只要去掉元素名,剩余的就是类型;

      三目运算符a>b?a:b,':'前后类型要相同;

================================================

11.结构体变量做函数参数时,要传递的是地址;

 

12.(heap):

#include<stdio.h>

#include<stdlib.h>

int main()

{

double *p=(double*)malloc(sizeof(double));

int *a=calloc(5,sizeof(int));

printf("p=%p,a=%p\n",p,a);

*p=12.23;

int i;

for(i=0;i<5;i++)

{

a[i]=i+10;

}

free(p);

a=realloc(a,10);//对原来a空间重新分配10空间

free(a);

}

 

12.1:对于事先不知道需要多大空间时,用到malloc,即动态内存,不受作用范围限制;

12.2:有申请就要有释放;


C++

1.C++中成员地址和函数地址,都为true。

2.引用:

3.C++不提倡用宏。

4.C++类型转换:

static_cast数值类型之间,有一方是void*的指针类型之间 

例如:int n=static_cast<int>(46.25);

const_cast用于临时去掉const、volatile限制

例如:int n=10;

              const int k=n; const_cast<int&>(k)=23; 

reinterpret_cast 任意两种指针类型之间,指针于数值类型之间  

例如:float f=123.12;

p=reinterpret_cast<int*>(&f);                               

dynamic_cast 

5.关键字:~compl   ^xor     !not      |bitor  ||or   &bitand           

  &&and  !=not_eq   &=and_eq   |=or_eq  ^=xor_eq

          new:new 类型  

  delete:

  new和delete:

#include<iostream>

#include<cstdlib>

using namespace std;//new 类型==>(类型*)malloc(sizeof(类型))

int main()

{

int* p=static_cast<int*>(malloc(sizeof(int)));

int* q=new int;//不保证是零

int* r=new int (888);//用888初始化*r

int n=10;

int* a=new int[n];//不保证是零

delete r;r=NULL;

delete q;q=NULL;

delete []a;a=NULL;//释放一片空间

free(p);//malloc申请的要用free释放

return 0;

}

 

6.函数地址和成员地址输出都为true。cout<<&main<<endl;

 

7.函数在代码区,数据在数据区,sizeof时,函数不会有大小。

 

8.char next()const{return a[cur++];}//此处的const表示不会修改当前对象

 

9.求最大公约数:

int maxcd(int a,int b){

     if(a==0) return b;

     return maxcd(b%a,a);

   }

 

10.C++类中,不管什么变量,至少占一个字节(内存分配,是以字节为单位);

   new一个数组的时候会额外分配4个字节,来保存数组中元素个数,这样delete时才知   道释放多少;x=new A[3];sizeof(x)=7,即3+4;

 

11.指针只能保存地址,如果要保存字符串,用数组 如:char a[100];

 

12.继承:子类先调用父类的构造函数;

   虚基类构造函数参数由底层子类直接传递

   父类构造顺序按照继承顺序   

   继承,避免代码重写,子类对象一定是父类对象;

 

13.多态:只有通过指针调用虚函数是,才会实现多态;

        一个类,如果它的实现交给子类来实现,那么就写成虚函数;

         多态:继承、虚函数、指针或引用;

         构造、析构函数中没有多态(子类先调用父类的构造函数,子类的);

 

14.应用(&)是C++特有的;

 

 

1...静态成员函数,友元函数,虚基类;

一个函数操作对象不依赖当前对象(整体行为),定义为静态成员函数,静态成员变量在类外初始化,因为它属于整个类;

 

 

附录:

1:const对指针操作实例

#include<stdio.h>

#include<string.h>

void main()

{

char a[20]={'h','e','\0','w','o'};

"csd1007";

puts(a);//he

puts("csd1007");//csd1007

char *p=a;

printf("%c\n",*p);//h

//printf("%s\n",p);//he

*p='w';

puts(a);//we

p="csd1007";//编译器可能会有警告

printf("%c\n",*p);//c

//*p='w';//断错误

const char *q=NULL;//等价char const *q=NULL;

q="csd1007";//只是把字符串第一个地址赋给指针q

//*q='w';//q只读,不能赋值

p=a;

strcpy(a,"NB");

puts(a);//NB

q=a+3;

puts(q);//wo

char *const r=a;//表示指针r是一个常量

*r='A';

puts(a);//AB

//const char *m表示对对所指的目标只能进行读操作

//char *const n表示此指针只能进行读操作

 

}

 

2:程序4--利用二级指针返回字符串

#include<stdio.h>

int fun(const char *cstr,const char **q)

{

int r=0;

while(isdigit(*cstr))

{

r=r*10+*cstr-'0';

cstr++;

}

*q=cstr;

return r;

}

void main()

{

const char *str=NULL;

int n=fun("123abc",&str);

printf("%d,%s\n",n,str);

}

 

结果:123abc

 

3:动态数组

动态数组:

#include<iostream>

using namespace std;

char mem[10000];

int pos;

class A{

public:

  A(){cout<<"A()"<<endl;}

  ~A(){cout<<"~A()"<<endl;}

  

  static void* operator new(size_t bytes)

  {

    cout<<"new A"<<bytes<<endl;

    int alloc=pos;

    pos+=bytes;

    return mem+alloc;

  }

  void operator delete(void *p){cout<<"delete A"<<endl;}

  static void* operator new[](size_t bytes)

  {

    cout<<"new A[]"<<bytes<<endl;

    int alloc=pos;

    pos+=bytes;

    return mem+alloc;

  }

  void operator delete[](void *p){cout<<"delete A[]"<<endl;}

};

int main()

{

  A* x=new A;//1、分配空间;2、执行构造函数

  delete x;//1、执行析构函数;2、释放空间

  x=new A[3];

  delete[] x;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

顶 0踩 0收藏
文章评论
    发表评论