C语言笔记

一下内容大部分是自己写的,也查了一些资料,没有细致标明,致谢愿在互联网贡献的人。 

(一)

0、exit()就是退出,传入的参数是程序退出时的状态码,0表示正常退出,其他表示非正常退出,一般都用-1,标准C里有EXIT_SUCCESSEXIT_FAILURE两个宏,用exit(EXIT_SUCCESS);可读性比较好一点。

使用exit()时,可以不论main()的返回值类型

1、void*malloc(int size)  

malloc 向系统申请分配指定size个字节的内存空间,返回类型是void*类型,void*表示未确定类型的指针,c,c++规定void*类型可以强制转换为任何其他类型的指针

2

加深alloc,init方法的理解,正如上面的malloc是分配内存,alloc也是分配内存,就是在计算机里面开辟一块区域用来放东西,可以想象一下:大学新生入学,接待新生,学校空出有座位的教室来接待新生,初始化,就是在座位上(空间里)放一些水果茶水等,就是附一个初始的值,我们在前面打印一个初始化的数组,发现也是有基本值的,这就是初始化init.

3、int strcmp(const char *str1,const char *str2)

其作用为:

将str1的各个字母的ASCII码与str2的进行比较,若str1 > str2则返回大于0的数,若相等则返回0,否则返回负数。

4、struct,enum还有class的区别

枚举的定义格式可以跟结构体相同,但是也有特殊的定义法,在oc语言里面,typedef 系统关键字 (NS_ENUM(通用),NS_OPTIONS(主要用于位移操作))(NSInteger,枚举名){
};

enum关键字用于声明枚举,即一种由一组称为枚举数列表的命名常熟组成的独特类型,主要是增加可读性

结构体struct,同时定义多个不同类型的变量。

struct 里面可以镶嵌枚举值,也可以镶嵌struct,但是枚举就不能镶嵌enum和struct,因为struct可以允许里面有不能类型,enum要求里面的类型基本差不多,同类型。

typedef struct Car_t {

             float m_depth;

             float m_height;

            struct Cupboard_t {

             bool  m_flag;

             float m_width[5];

            } Cupboard_t;

}Car_t;


struct Drawer_t {    

         enum Axis {

                               X,

                                T,

         }m_axis;

         float m_height;

         float m_depth;

}m_drawer;

5、tolower

把字符转换成小写字母,非字母符不做处理


6、sizeof用法

sizeof(object);sizeof(对)

sizeof(type_name);sizeof(类型)

sizeofobject;sizeof对象

7、c语言语法

—>符号用法(见另一个文档)

8、&符号用法

9.1&a是取a的内存地址

&&逻辑运算符

10、fgets函数用来从文件中读入字符串。fgets函数的调用形式如下:fgets(str,n,fp);此处,fp是文件指针,str是存放在字符串的其实地址;n是一个int类型变量。函数的功能是从fp所指文件中读入n-1字符串放入str为起始地址的空间内;如果在未读满n-1个字符之时,已读到一个换行符或一个EOF(文件结束标志),则结束本次读操作,读入的字符串中最后包含读到的换行符。因此,确切的说,调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加‘\0’,并在str作为函数值返回。

11、strlen 所作的仅仅是一个计算器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到

碰到第一个字符串结束符‘\0’为止,然后返回计算器值

12、atof函数名

功能:把字符串转换成浮点数

(二)

1、我们要存储一个数据,我们也知道一个字节有唯一的地址,如果数据不是太大一个字节就可以存储,那数字对应唯一地址,但是如果数字比较大,一个字节存不下,我就知道不少数据类型(长整形,浮点型等等)也都不只分配一个地址,那这个数据的地址怎么表示呢???

变量的地址就是分配内存的第一个字节的地址,如果要查字节后面的地址,只要相加1就行。如果要查另一个变量的地址只要相加其实地址到现在地址中间隔了多少个字节就行。

2、像素是什么??

从定义上来讲,像素是指基本原色素及其灰度的基本编码。像素是构成数码影像的基本单元,通常以像素每英尺为单位来表示影像分辨率的大小。

3、自然界中的所有颜色都可以由红、绿、蓝(R、G、B)组合而成

对于32位的RGB位图像素数据格式是:

蓝色B值绿色G值红色R值透明通道A值,A equal Alpha

4、对循环以及条件判断的一些辅助了解

在条件判断还有循环语句在后面如果没有括号,都是在判断条件后执行条件或者循环语句后的最近语句,

continue语句,使用在循环语句,如果i = 1,然后执行到continue语句后,继续执行i = 2,但是break就不一样,如果执行到break语句就是跳出循环了;这与swith多项选择语句一样,遇到break都是跳出了swith,如果没有break语句就执行下一个case,如果所有的case都不符合条件,我们就跳到default语句。

return 语句就是直接回到函数的源头,返回一个值,一般程序执行到这里,后面所有的代码都不需要执行了,这比break更直接了断,break只是跳出循环,而return直接跳出来了。

5、计算机都是从右往左运算的

6、*与指针的关系,*号首先它是声明一个指针变量,*号还可以用来计算,*A(指针名),就是找到指针A对应的数据。

int number;

int bbb;

int *p = &number;

int ccc = *p + 5;

上面这两个*含义完全不一样的,前者是形式符号,表明p是一个指针变量,后者*是一个运算符,*p是指指针p对应的数值。

7、计算机运算符的优先级是什么样的,这个可以以后好好研究一下。

8、scanf(“  %d”,pvalue).这句话的意思有两种理解,如果pvalue是一个普通的数(非指针),那么我们从键盘上面输入的值赋值给这个变量,如果它是指针,那么键盘输入的值就赋值给指针指向的变量。

这中理解其实不太对,后面的参数都必须是指针,都是一个地址,只是有些形式不同罢了。

有的事&number,有的直接就是一个指针,其实&number是一个地址本质也是一个指针

9、指针和普通数据的区别就是:这两者的区别可以理解为数学里面的矢量和数量的区别,指针虽然是一个数,但是它是有方向性的,就像矢量也是有方向一样,所以上面那个语句中的pvalue,pvalue是指针还是普通变量名就有很大的区别。

10、char mutilple[ ] = “a string”;

char *p = multiple;


(三)

SizeofStrlen的区别与联系(转)

1.sizeof操作符的结果类型是size_t,它在头文件中typedefunsigned int类型。

该类型保证能容纳实现所建立的最大对象的字节大小。 

2.sizeof是算符,strlen是函数。 

3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。

sizeof还可以用函数做参数,比如: 

short f();

printf("%d\n", sizeof(f()));

输出的结果是sizeof(short),即2 

4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。 

5.大部分编译程序在编译的时候就把sizeof计算过了是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因 

char str[20]="0123456789";

int a=strlen(str); //a=10;

int b=sizeof(str); //b=20;

6.strlen的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。 

7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

8.当适用了于一个结构类型时或变量, sizeof返回实际的大小,

当适用一静态地空间数组, sizeof 归还全部数组的尺寸。

sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸 

9.数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,

如: 

fun(char [8])

fun(char [])

都等价于 fun(char *) 

C++里参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小

如果想在函数内知道数组的大小, 需要这样做:

进入函数后用memcpy拷贝出来,长度由另一个形参传进去 

fun(unsiged char *p1, int len)

{

  unsigned char* buf = new unsigned char[len+1]

  memcpy(buf, p1, len);

}

(四)

我们能常在用到 sizeof strlen的时候,通常是计算字符串数组的长度

看了上面的详细解释,发现两者的使用还是有区别的,从这个例子可以看得很清楚:

char str[20]="0123456789";

int a=strlen(str); //a=10; >>>> strlen 计算字符串的长度,以结束符 0x00为字符串结束。

int b=sizeof(str); //b=20; >>>> sizeof计算的则是分配的数组 str[20]所占的内存空间的大小,不受里面存储的内容改变。  

上面是对静态数组处理的结果,如果是对指针,结果就不一样了

char* ss = "0123456789";

sizeof(ss) 结果 4===》ss是指向字符串常量的字符指针,sizeof获得的是一个指针的之所占的空间,应该是

长整型的,所以是4

sizeof(*ss) 结果 1===》*ss是第一个字符其实就是获得了字符串的第一位'0'所占的内存空间,是char类型的,占了 1

strlen(ss)= 10 >>>> 如果要获得这个字符串的长度,则一定要使用 strlen


运算符和函数,要说区别,大概也就是

1)语法形式上会有区别;

2)运算符只能重载,不能自定义,函数的名字随便你起,只要是个标志符就行;但运算符不行,比如,你无法仿照其它语言的符号,自己定义一个乘方运算符“**”

3)任何函数都可以重载或者覆盖,但通常你不能改变运算符作用于内置类型的行为,比如你不能通过重载“operator+”,让3 + 2产生出6来。


至于newmalloc,这是两个具体的东西,这两个倒是有本质的区别,而不仅仅是语法形式的区别。比如,至少malloc不会调用构造函数,而new会;malloc不会抛出异常,而new会;你无法重新定义malloc失败时的默认行为(返回null),但你可以重定义new失败时的默认行为,比如不让它抛出异常。



->是一个整体,它是用于指向结构体、C++中的class等含有子数据的指针用来取子数据。换种说法,如果我们在C语言中定义了一个结构体,然后申明一个指针指向这个结构体,那么我们要用指针取出结构体中的数据,就要用到“->”.

举个例子:

struct Data

{

   int a,b,c;

};              /*定义结构体*/

struct Data * p;/*定义结构体指针*/

struct Data A = {1,2,3};/*声明变量A*/

int x;/*声明一个变量x*/

p = &A ; /*p指向A*/

x = p->a;/*这句话的意思就是取出p所指向的结构体中包含的数据项a赋值给x*/

         /*由于此时p指向A,因而 p->a == A.a,也就是1*/


对于一开始的问题 p = p->next;这应该出现在C语言的链表,这里的next应该是一个与p同类型的结构体指针,其定义格式应该是:

struct Data 

{

   int a;

   struct Data * next;

};/*定义结构体*/

…………

main()

{

   struct Data * p;/*声明指针变量p*/

  ……

   p = p->next;/*next中的值赋给p*/

}

链表指针是C语言的一个难点,但也是重点,学懂了非常有用。要仔细讲就必须先讲变量、指针。

什么是变量?所谓变量,不要浅显的认为会变得量就是变量。套用我们院长的问话:教室变不变?变,因为每天有不同的人在里面上课,但又不变,因为教室始终在那,没有变大或变小。这就是变量:有一个不变的地址和一块可变的存储空间。正常情况下,我们只看到变量这个房间里面的东西,也就是其内容,但不会关注变量的地址,但是C语言的指针,就是这个房间的地址。我们声明变量就相当于盖了间房子存放东西,我们可以直接观看房子里的东西,而声明指针,就是相当于获得了一个定位器,当用指针指向某个变量时,就是用指针给变量定位,以后我们就可以用指针找到他所跟踪的变量并可以获得里面的内容。

那结构体呢?结构体就相当于是有好几个房子组成的别墅,几个房子绑定在一起使用。假设现在有很多这种别墅分布在一个大迷宫里,每间别墅里都有一间房子。里面放了另一个别墅的位置信息,现在你手拿定位器找到了第一栋别墅,从里面得到了你想要的东西(链表的数据部分),然后把下一栋别墅的位置计入你的定位器p = p->next),再走向下一栋别墅……如此走下去,知道走到某地下一栋别墅信息没有了(p->next ==NULL),你的旅行结束。这就是链表一次遍历的过程。现在你能明白 p=p->next的含义了吧!

写了这么多。希望你能明白。

如果想学好cC++,链表和指针必须熟练掌握!

(五)

1scanf()函数不允许读入含有空格的完整字符串,而是在第一个空白字符串停止读取,ges()函数读取输入的表达式,这个函数会读入整行输入,包含空格。可以将输入和整个程序的循环结合在一起。

2、‘’单引号引用字符,而“”双引号引用字符串

3、是不是引号引用用’\’’,还有’\0’,为什么要这么做呢。


(六)

1%d代表十进制

%u代表无字符变量

%c代表字符变量


(七)

1、计算机时很墨守成规的,但却是最严谨最精确的最听话的,作为工程师,你要做的,就是要了解他的运行规则,比如

if ((*(pbuffer + index) = getchar()) == '\n') 

    *(pbuffer + index ++) = '\0';

就像这个代码

其实看上去很简单,但是却是很复杂,看上去只有两句话,但其实分为好几个步骤,

首先第一步:赋值

*(pbuffer + index) = getchar()

第二步:判断是否相等

if(getchar() == ‘\n’)

第三步:还是赋值

如果相等那就把‘\0’赋值给*(pbuffer + index)即*(pbuffer + index) = ‘\0’

第四步:索引值加上1

即index = index + 1


它为什么能这么简单的写了,我们要了解这里的运算符的优先级

看if括号里面,首先执行的是括号里面的,()优先级最强

这里我还是不太会啊,找到了正解

a++与++a的区别!!!!!!

程序是按照步骤来的,如果是a++的话,在那一行代码中,a的值是不变的,下一行才发生变化,++a则是在那一行已经发生了变化。

a++是先执行表达式后再自增,执行表达式时使用的是a的原值。

++a是先自增再执行表达示,执行表达式时使用的是自增后的a

例:

int a=0

printf("%d",a++); //输出0,执行完后a=1


int a=0

printf("%d",++a);//输出1,执行完后a=1

(八)

1、多维数组,size[n][m]

如果我们将多维数组和指针结合起来,size是一个指针,*size还是一个指针,等于size[0],多维数组是元素是数组的数组,size[0]是大数组的第一个元素的地址

2、size_t和无符号类型有什么区别??????

3、在编写程序时,不论是判断语句还是循环语句,我们有时在if或者for后面加一个大括号{},

有的时候没有加,比如

for (size_t i= 0 ;i<count;i++)

     if(!(found = (trial % *(primes + i))))

           break;


    if(found)

         *(primes + count ++ ) = trial;

这里很容易误解,每执行一步,然后下面两个if语句都会执行,其实第一个if才是for的执行语句,只有当上面的循环结束了才会执行下面的if,可以在执行的第一个if加一个大括号{},如下

for (size_t i= 0 ;i<count;i++){

     if(!(found = (trial % *(primes + i))))

           break;

}


    if(found)

         *(primes + count ++ ) = trial;

为什么上面不加,并且我们发现很多情况都没有加,就是应该for循环后面需要执行的语句就一句,再加就显得多余了,但是如果后面两个if都是在for循环的执行语句,我们就要加一个大括号了。如下

for (size_t i= 0 ;i<count;i++){

     if(!(found = (trial % *(primes + i))))

           break;


    if(found)

         *(primes + count ++ ) = trial;

}

结论,不论是if还是for,如果后面的执行语句大于1,我们需要加一个大括号,否则就不需要加。


4、while(count < total) {

}

这是一个无线循环,只要count<total就会执行,相当于

for(;  count<total;  ){

}

没有初始要求,也没有循环后的运算,这里可能是:初始条件已在循环前具备,而一个循环结束后之所以没有进行运算,可能就在循环结束前就已经做了。

5、我们经常看到*p = 2;*(p+1)= 3;

然后我们就说p+1是下一个数的地址,我觉得这样:这只是一种形式地址或者是地址名称,不是真实的地址值。其实,如果我们只给这个一个字节来装这个数,那么下一个数的真实地址确实是比前一个地址数值增一,但是如果我们给了多个字节(long四个,int两个等),那么真实的地址增值就不止1,但是我们的形式地址还是p+1,这是我的理解。

6、 char *pS[NUM_P] = { NULL };

这里是数组,不过数组里面放的全部都是指针,地址

7、

数组是有序的,链表是无序的

两者各有优缺点

数组因为没有顺序,所以存取速度很快,链表是无序的,所以他能高效的利用内存空间,但速度就慢了。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值