数组
#define N 10 int a[N]; for(int i=0;i<N;i++) { a[i] = 0; } //初始化,没有被初始化到的数组下标就被设置为0 int a[10] = {1,2,3,4,5}; //等价于 int a[10] = {1,2,3,4,5,0,0,0,0,0}; //也可以写成入如下形式相当于把整个数组全部赋值为0 int a[10]={0}; //C99中可以指定对某个元素下标赋值,剩余的就被赋值为0 int a[15] = {[2]=11, [9]=33, [14]= 99}; //对数组使用sizeof运算符 int a[10]; sizeof(a); //结果就是40 //sizeof 返回的是无符号的整形size_t,无符号和有符号之间运算会有危险, //最好使用强制转型 //数组清零 #define SIZE ( (int)(sizeof(a)/sizeof(a[0])) ) //多维数组初始化 int m[5][9] = {{1,2,3,4,5,6}, {2,3,54,5,6}, {4,5,6,7,8}, {3,5,6,7,11}}; //也可以省略外面的一层大括号 int m[5][9] : {1,2,3,4,5,6, {2,3,54,5,6, {4,5,6,7,8, {3,5,6,7,11}; //常量数组 const char hex_chars[] = {'0','1','2','3'}; //C99中也可以对多维数字进行指定下标的初始化 //C99还支持变长数组
指针
//定义一个指针 int *p; //每个指针变量只能指向一种特定的类型 int *p; double *d; char *r; //赋值和访问 &运算符是获取一个变量的地址值, *那个运算符是间接寻址 int i, *p; i = 10; p = &i; printf("%d",*p); //这样的赋值是错误的 int i, *p; i = 10; *p = &i; //这里是将 i的地址赋予p指向的内容,所以是错误的 //*p是指针指向的内容,是一个具体的值,p才表示一个地址,所以 //应该是 p = &i; 将i的地址赋予指针p才是正确的 //指针作为返回值 int *max(int *a, int *b) { if(*a > *b) { return a; } return b; } //注意,永远不要返回指向局部变量的指针 int *f(void) { int i; return &i; } //一旦函数f返回,变量i就不存在了,所以变量i的指针将是无效的,有的编译器会 //在这种情况下给出类似"function returns address of local variable"的 //警告 //未初始化的指针变量指向的是一个不确定的内存地址值 //用const保护参数,也就是指针指向的内容是常量不可改变,但指针内容本身是 //可以被改变的,也可以包含指针本身,还可以包含指针本身和指针指向的内容 //第一种情况,保护指针指向的内容,此时指针本身可以改变 int number = 100; const int *p; //*p = 0; p = &number; //第二种情况,保护指针本身,指针指向的内容可以被改变 int *const p2; *p2 = 0; //p2 = &number; //第三种情况,包含指针本身,以及指针指向的内容 const int *const p3; //*p3 = 0; //p3 = &number;
指针和数组
//定义指针,指针p指向a数组的第一个元素 int a[10], *p; p = &a[0] //设置数组a有10个元素 p = &a[2]; //指向数组a的第三个元素 int *q = p+3; //指向数组a的第六个元素,也就是a[5] p -= 4; //指向数组a的第二个元素,也就是a[1] //两个指针之间可以相减,但是两个指针必须都指向同一个数组,因为比较的是内存 //地址,如果两个数组指向的是两个不同的数组,最后计算出来的结果可能是未知的 //内存
*运算符和 ++运算符(++运算符优先级高于*)
表达式 | 含义 |
*p++或者*(p++) | 先自增p的值,然后再获得*p |
(*p)++ | 自增前的表达式是*P,以后再自增*p |
*++p或*(++p) | 先自增p,自增表达式的值是*p |
++*p或++(*p) | 先自增*p,那个自增后表达式的值是*p |
//用数组名做指针 int a[10]; *a = 7; //等于a[0] = 7; //也可以通过指针来修改a[1] *(a+1) = 12; //等于a[1] = 12; //遍历 for(p=&a[0]; p<a[N]; p++) { sum += *p; } //处理多维数组 int a[NUM_ROWS][NUM_COLS]; int *p; for(p=&a[0][0]; p<= &a[NUM_ROWS-1][NUM_COLS-1]; p++) { *p = 0; } //C99中的指针和变成数组
指针的高级应用
//内存分配函数,这些都是声明在<stdlib.h>头文件中 //malloc()函数 分配内存块,但是不对内存块进行初始化 //calloc()函数 分配内存块,并且对内存块进行初始化 //realloc()函数 调整先前分配的内存块大小 //空指针用表示 不指向任何地方的指针,用名为 NULL 的宏来表示 //NULL 定义在<stdlib.h>中 p = malloc(1000); if(NULL == p) { //分配失败 } //malloc函数原型,它返回的是void*类型指针,所以需要转型,这个void*就代表 //任何类型 void *malloc(size_t size); //分配字符串时需要分配n+1大小空间,因为字符串最后是\0结尾 p =(char*) malloc(n+1); //分配数组空间,注意分配时必须使用sizeof计算单个值占多少字节 int *a; a = malloc(n * sizeof(int)); //calloc函数原型,为nmemb个元素的数组分配内存空间,其中每个元素长度 //都是size个字节,如果要求的空间无效会返回空指针 void *calloc(size_t nmemb, size_t size); a = calloc(n, sizeof(int)); //realloc函数原型,其中ptr必须指向先前通过malloc,calloc,realloc的调用 //获得的内存块,size表示新尺寸可能会大于或小于原有尺寸。 void *realloc(void *ptr, size_t size);
C标准列出了几条关于realloc函数的规则
1.当扩展内存块时,realloc函数不会对添加进内存块的字节数进行初始化
2.如果realloc函数不能按要求扩大内存块,那么它会返回空指针,并且在原油的内存块中的数据不会发生改变
3.如果realloc函数调用时以空指针作为第一个实际参数,那么它的行为就像malloc函数一样
4.如果realloc函数被调用时以0作为第二个实际参数,那么它会释放掉内存。
注意:一旦realloc函数返回一定要对所有指针进行更新,因为ralloc函数可能会使内存块移动到了其他地方
//用free函数释放动态申请的内存,其原型为 void free(void *prt); //悬空指针问题 char *p = malloc(4); free(p); strcpy(p, "abc"); //此时p指向的内存已经被释放掉了,再对其修改可能会造成 //严重的错误 //结构体 struct node { int value; struct node *next; }; struct node *new_node= NULL; new_node = malloc(sizeof(struct node)); //写成这样是不对的,我们需要申请结构体大小的空间,而这样申请的是指针大小的 //空间,一个指针可能是4个字节,这样实际上就申请了4个字节 new_node = malloc(sizeof(new_node)); // ->运算符 (*new_node).value = 10; //等价于 node_new->value = 10; //指向指针的指针 char **ptr; *ptr = "abc"; //ptr是指向"abc"的地址 //指向函数的指针 //假设函数integrate的原型如下: (*f)说明f 是个指向函数的指针 double integrate(double (*f)(double), double a, double b); //也可以写成: double integrate(double f(double), double a, double b); //调用integrate时,将把一个函数名作为第一个实际参数,注意sin后面没有括号 //C编译器会产生指向函数的指针而不是产生函数调用的代码 result = integrate(sin, 0.0, PI/2); //在函数integrate中, *f 表示调用f 所指向的函数,*f 就是调用sin函数 // (*f)(x) 和f(x)都是一样的,但是用(*f)(x)更好,说明是f是指向函数的指针 //C函数库中的qsort函数原型 void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)); //base是指向数组中的第一个元素,nmemb是要排序元素的数量,size是每个 //数组元素的大小,compar是指向比较函数的指针 int compare_parts(const void *p, const void *q) { const struct part *p1 = p; const struct part *p2 = q; if(p1->number < p2->number) { return -1; } else if(p1->number == p2->number) { return 0; } return 1; } //还可以写成: int compare_parts(const void *p, const void *q) { return ((struct part*)p)->number - ((struct part*)q)->number; } //指向函数的指针,可以指向任何参数是int,返回void类型的函数 void (*pf) (int); void fun(int x); pf = fun; //让pf指向函数fun,注意fun前面不需要加 & pf(100); //受限指针 int * restrict p; //灵活数组成员 struct vstring{ int len; char chars[N]; }; //这里N表示一个字符串最大长度的宏,但是分配最大长度会导致浪费,于是采用 //如下方式申明chars长度 struct vstring{ int len; char chars[1]; }; struct vstring * str = malloc(sizeof(struct vstring) +n-1); //这样就看以达到目的了,并且内存不会浪费,这样叫 struct hack 技术 //C99支持灵活数组成员,当结构体最后一个是数组时可以省略长度 struct vstring{ int len; char chars[]; };
定义NULL为
#define NULL (void*)0;
如果把NULL 定义为0,那么把NULL赋给整型变量index是合法的,但是把NULL定义为(void*)0 则表示把指针赋值给了整型变量
将malloc函数的值类型强制转换没有任何好处,这是来自于经典C的习惯。
参考:
相关推荐
C语言全套资料 C语言程序设计 C语言算法 C语言课件 C语言顺序程序设计,C语言数组,C语言循环控制,C语言预处理命令,C语言文件操作指针,C语言选择结构程序设计,C语言结构体与共用体,C语言文件操作,C语言函数
这里有c语言的大多数语法实例供参考, 包括基础关键字, 宏定义 ,指针,结构体,共同体,大小端转换,数据交换,递归,零长数组的使用,等.供学习与借鉴
为了利于C语言的全面推广,许多专家学者和硬件厂商联合组成了C语言标准委员会,并在之后的1989年,诞生了第一个完备的C标准,简称“C89”,也就是“ANSI C”,截至2020年,最新的C语言标准为2018年6月发布的“C18”...
C语言基本语法归纳及实例介绍 C语言概况 C程序的结构 数据类型、运算符与表达式 最简单的C程序设计—顺序程序设计 选择结构程序设计 循环控制 数组 函数 指针
C语言教程(算法、数组、函数、指针)全方位讲解PPT合集: C语言出错信息速查.pdf C语言教程之函数讲解.ppt C语言教程之指针讲解.ppt C语言教程之数组讲解.ppt C语言教程之算法的讲解.ppt C语言经典案例100例.rar ...
c语言指针常见指针及如何使用附带相关基本概念 C语言中的指针是一种特殊的数据类型,它存储了一个内存...使用C语言指针需要掌握指针的基本概念和语法规则,理解指针的应用场景和注意事项,才能编写出高效、可靠的程序。
each函数返回数组中当前的键/值对并将数组指针向前移动一步 基本语法 array each ( array &$array ) 在执行 each() 之后,数组指针将停留在数组中的下一个单元或者当碰到数组结尾时停留在最后一个单元。如果要再用...
学习完这一套15个函数,你的c语言就过关了,数组,指针,函数,结构体,共用体,枚举,都不是事儿。
学习C语言的基础知识,如关键字,语法,数组,指针
本文主要介绍c语言的入门知识,包括语法,数组,指针,语句控制结构等
数组和指针是C语言编程中的重要数据结构,它们可以帮助您更好地管理和操作数据。文件操作和预处理指令是C语言编程中的其他重要方面,它们可以帮助您更好地处理文件和优化代码。 通过学习这份课件,您将可以轻松地...
很详细,和第四版配套 语法形式 存储类型 数据类型 *指针名=初始地址; 例: int *pa=&a; 注意事项 用变量地址作为初值时,该变量必须在指针初始化之前已说明过,且变量类型应与指针类型一致。 可以用一个已赋初值...
each()定义和用法 each() 函数生成一个由数组当前内部指针所指向的元素的键名和键值组成的数组,并把内部指针向前移动。 返回的数组中包括的四个元素:键名为 0,1,key 和 value。单元 0 和 key 包含有数组单元的键...
C语言语法知识点,数组,指针,构造函数等等.
C语言的基本语法: 2. C语言分支与循环 3. C语言函数 4. C语言数组 两个小项目: 5. C语言实现三子棋 6. C语言实现扫雷 了解C语言更多细节: 7. C语言操作符 学习指针: 8. C语言指针初阶 学习结构体: 9. C语言...
谭浩强的《C语言程序设计》第五版共分为14章,从C语言的基础语法、数组、指针、函数、结构体、文件操作等方面进行了详细的讲解。每一章都包含了大量的代码示例,这些示例不仅能够帮助读者理解书中的理论知识,还能够...
首先是C语言的基础语法:变量、字符串、条件、循环、数组、函数、结构体等,然后就是指针、内存管理等C语言中至关重要的两大标准。 因此,学习C语言推荐大家可以从《C Primer Plus》开始入门,系统地了解C语言的...
你可以从学习基本的语法、数据类型、控制流程开始,然后逐步深入了解函数、数组、指针等概念。为了更好地学习C语言,你可以寻找一些经典的教程和书籍,比如《C Primer Plus》、《C Programming: A Modern Approach》...
第2篇是基础知识,详细介绍C语言的语法规则和如何利用C语言进行程序设计的方法。第3篇是能力提高,通过大量实例将函数、数组、指针、结构体、文件操作等知识介绍给读者。第4篇是高级实践,通过对数据结构、算法的...
C语言基本语法:包括函数、数组、指针、结构体等基本语法特性。 C语言程序设计:包括程序设计的基本流程、算法设计方法和调试技巧等。 C言标准库函数:包括输入输出函数、字符串处理函数、数学函数等。 C语言应用...