- sizeof和strlen的区别:
1、sizeof:
sizeof是既是关键字又是运算符,但不是函数。功能:返回保证能容纳实现所建立的最大对象的字节数。参数:可以是数组、指针、类型、对象、函数等。返回值:跟数组、对象等所存储的内容没有关系。作用时间:编译期就计算完成。
2、strlen:
strlen()是函数。功能:返回字符串的长度。参数:必须是字符型指针(当数组名作为参数传入,实际上退化为指针)。返回值:从首地址开始遍历,直到遇到'\0'结束,但不包括'\0'。作用时间:运行时才进行计算。
- printf函数:
printf函数的参数计算是从右向左进行的。返回值为输出的字符个数。
- malloc函数:
1、原型:extern void *malloc(unsigned int num_bytes);
2、头文件:#include <malloc.h> 或 #include <alloc.h>或#include<stdlib.h> (注意:alloc.h 与 malloc.h 的内容是完全一致的)
3、功能:分配长度为num_bytes字节的内存块。
***说明:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
当内存不再使用时,应使用free()函数将内存块释放。
4、声明:void *malloc(int size);
***说明:malloc 向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。如果你写成:p = malloc (sizeof(int)); 则程序无法通过编译,报错:"不能将 void* 赋值给 int * 类型变量"。所以必须通过 (int *) 来将强制转换。
void get_str(char *ptr) { ptr=(char*)malloc(17); strcpy(ptr,"Xiyou Linux Group"); } int main(int argc,char *argv[]) { char *str=NULL; get_str(str); printf("%s\n",str); }
***这段代码有4处错误:
① malloc函数应该开辟18个字节的空间,因为字符串结尾会自动补‘\0’,加上它一共18字节。
② “值传递”为单向传递,形参值无法传回实参,不能实现复制并输出字符串的功能。所以可以使用二级指针,“址传递”实现双向传递。
③ malloc是在堆上分配的内存,不会随着函数调用结束而自动释放,应该在主函数里用free()函数将其释放。
④ 主函数里没有返回值,应该加上return 0。
***修改后的代码如下:
#include #include #include void get_str(char **ptr) { *ptr=(char*)malloc(18); strcpy(*ptr,"Xiyou Linux Group"); } int main() { char *str=NULL; get_str(&str); printf("%s\n",str); free(str); return 0; }
- 指针函数与函数指针:
1、指针函数
指针函数指 带指针的函数,即本质是一个函数,函数返回类型是某一类型的指针。声明格式如下:
类型标识符 *函数名(参数表)
也可以这样声明:int *fun(int a,int b);
让指针标志 * 与int紧贴在一起,而与函数名fun间隔开,这样看起来更容易理解。int* fun(int a,int b);
函数返回值必须用同类型的指针变量来接受,也就是说指针函数一定有函数返回值,而且在主调函数中,函数返回值必须赋给同类型的指针变量。比如:
float *fun(); float *p; p = fun(a);
2、函数指针
函数指针是指向函数的指针变量,即本质是一个指针变量。指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:
类型标识符 (*函数名)(参数表)
int (*f)(int x); //声明一个函数指针 f = func; //将func函数的首地址赋给指针f
其实这里f不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成一个返回整型指针的函数的原型声明。
- 二维数组:
二维数组元素的存放顺序在C语言中是按行优先存放的。它在逻辑上是二维的,但是实际的硬件存储器却是连续编址的,也就是说存储器单元是按一维线性排列的。
如果用指针来理解的话,比如:
int a[5][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}}; int (*p)[5]; p = a;
a是一个数组名,类型是指向一维数组的指针,指向这块连续空间的首地址,值是&a[0][0],所以a是指针常量,即不能有a++,a=p这种操作。
a[1]是一维数组名,类型是指向整型的指针,值是&a[1][0],这个值是一个常量。
p是一个数组指针变量,指向一维数组的指针变量,值是&a[0][0],可执行p++,p=a这种操作。
a+1表示指向下一行元素,也可以理解为指向下一个一维数组。
*(a+1)是取出第一行的首地址。a+1是对地址的偏移,所以取值后还是一个指针或地址。
- const关键字:
const是关键字,它的作用是阻止一个变量被改变。在一个函数声明中,const可修饰形参,表明它是一个输入参数,在函数内部不能改变其值。
*是指针的意思,表示地址;const是常量的意思,表示内容。
谁在前先读谁,前面的是不可改变的。
const char *p;
char const *p;
这两个等价,表示字符型常量指针,本质是指针,指向的内容不变,但是地址可变。char *const p;
表示字符型指针常量,本质是常量,指向的内容可变,但是地址不变,所以必须进行初始化。
const char *const p;
表示指向常量的字符型指针常量,内容地址均不可变。
- Linux和Windows下stdout,stderr的不同:
对比下面程序在Linux和Windows上的输出结果:
#include int main(int argc,char *argv[]) { while(1) { fprintf(stdout,"Group "); fprintf(stderr,"XiyouLinux"); getchar(); } return 0; }
在Linux下运行结果如下,当输入123\n时,输出结果为最后一行的内容。
stdout——标准输出设备stderr——标准错误输出设备两者默认向屏幕输出。在LInux下 ,stdout是行缓冲的,他的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。
而stderr是无缓冲的,会直接输出。举例来说就是fprintf(stdout,"xxxx");会缓存,直到遇到新行才一起输出。而fprintf(stderr,"xxxxx");不管有没有\n,都输出。
- 大端与小端
关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。这个其实讽刺当时英国和法国之间持续的冲突。Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。
Big-Endian(大端)和Little-Endian(小端)的定义如下:
1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。高/低字节:
在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。
就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。
所以它在内存中的表示形式为:
1)大端模式:
低地址 -----------------> 高地址
0x12 | 0x34 | 0x56 | 0x78(高字节)
2)小端模式:
低地址 ------------------> 高地址
0x78 | 0x56 | 0x34 | 0x12(低字节)
可见,大端模式和字符串的存储模式类似。图片更好理解。
所以我们现在知道采用大小模式对数据进行存放的主要区别在于在存放的字节顺序,大端方式将高位存放在低地址,小端方式将高位存放在高地址。采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。到目前为止,采用大端或者小端进行数据存放,其孰优孰劣也没有定论。
有的处理器系统采用了小端方式进行数据存放,如Intel的奔腾。有的处理器系统采用了大端方式进行数据存放,如IBM半导体和Freescale的PowerPC处理器。不仅对于处理器,一些外设的设计中也存在着使用大端或者小端进行数据存放的选择。
因此在一个处理器系统中,有可能存在大端和小端模式同时存在的现象。
=============================================================================
以上内容有部分是摘抄的,自己的总结能力还有待提高。
还有几个知识点没有整理到的,在以后的学习中会进行补充。
转眼大一已经快结束了,自己对C语言里很多东西的认识也只是停留在表层,这对以后更深层次的理解是很不利的。要知道C语言是目前编程的基础,把握当下,查漏补缺才是最重要的。
喵喵~加油↖(^ω^)↗