在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
-------------------------------------------------------------------- 回顾:[C语言]指针与字符串
指针的使用: /** * main.c by weiChen in 2015-5-4 */ #include <stdio.h> //定义函数体,使在main方法中能调用 void swap(int *pa, int *pb); void minmax(int c[], int len, int *min, int *max); int divide(int d, int e, int *result); int main(void) { /* 指针应用场景: 1. 交换两个变量的值 2. 函数返回多个值,某些值就只能通过指针返回; 传入的参数实际上是需要保存带回的结果的变量(注:函数中指针的值将作为参数传入函数); 3. 函数返回运算的状态,结果通过指针返回; 常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错; -1或0(在文件操作会看到大量的例子) 但是当任何数值都是有效的可能结果时,就得分开返回了; 后续的语言(c++,java)采用了异常机制来解决这个问题 4. 指针常见错误:定义了指针变量,还没有指向任何变量,就开始使用指针 */ int a = 5; int b = 6; swap(&a, &b); printf("a=%d,b=%d\n", a, b); int c[] = {1,2,3,4,5,9,30,13,45,59}; int min,max; minmax(c, sizeof(c)/sizeof(c[0]), &min, &max); printf("min=%d, max=%d\n", min, max); int d = 19; int e = 3; int f; if(divide(d, e, &f)) { printf("%d/%d=%d\n", d, e, f); } int i = 8; int *p; int k; k = 12; *p = 12;//未初始化变量,直接给指针赋值;一旦指针所指的位置不可写,程序将报错 printf("&i=%p\n", &i);//Segmentation fault return 0; } //交换两个值 void swap(int *pa, int *pb) { int t = *pa; *pa = *pb; *pb = t; } //求最小最大值 //虽然*min,*max是作为参数传进去的,但作用是得到结果,带入 void minmax(int a[], int len, int *min, int *max) { int i; *min = *max = a[0]; for(i=0; i<len; i++) { if(a[i] < *min) { *min = a[i]; } if(a[i] > *max) { *max = a[i]; } } } //@return 如果除法成功,返回1;否则返回0 int divide(int d, int e, int *result) { int ret = 1; if(e == 0) { ret = 0; } else { *result = d/e; } return ret; }
/** * main.c by weiChen in 2015-5-4 */ #include <stdio.sh> int main(void) { /* 指针与const 指针可以是const: 0xaffefado 值可以是const: 45 */ /* 指针是const: 表示一旦得到了某个变量的地址,不能再指向其他变量 int *const q = &i; //q的值是const,值是i的指针 *q = 26; //OK q++; //ERROR */ /* 所指是const:表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const) const int *p = &i; *p = 26; //ERROR, (*p是const) i = 26; //OK p = &j; //OK */ /* int i; const int *p1 = &i; \ | 指针不能被修改 int const *p2 = &i; / int *const p3 = &i; //判断哪个被const了的标志是const在*的前面还是后面 */ /* 转换:总是可以把一个非const的值转换成const的 void f(const int *x); //意思:传入一个const指针参数,但函数内部不会更改这个指针所指的值 int a = 15; //可以传入一个非const的指针的值 f(&a); //OK const int b = a; //也可以传入一个非const的指针的值 f(&b); //OK b = a + 1; //ERROR //当要传递的参数的类型比地址大的时候,这是常用的手段:既能用比较少的字节数传递值给参数,又能避免函数对外面的变量的修改 */ /* const数组: const int a[] = {1,2,3,4,5,6,}; 数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int (即a[0]等均为const) 所以必须通过初始化进行赋值 */ /* 保护数组值: 因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值 为了保护数组不被函数破坏,可以设置参数为const int sum(const int a[], int length); //不希望函数对参数作修改 */ return 0; }
指针的计算: /** * main.c */ #include <stdio.h> int main(void) { char ac[] = {0,1,2,3,4,5,6,}; //char数组 char *p = ac; //*p指向数组的第一个单元 printf("p = %p\n", p); //p = 0x7fff51f1dc15 printf("p + 1 = %p\n", p + 1); //p + 1 = 0x7fff51f1dc16 int ai[] = {0,1,2,3,4,5,6,}; //int数组 int *q = ai; //*p指向数组的第一个单元 printf("q = %p\n", q); //q = 0x7fff50160bf0 printf("q + 1 = %p\n", q + 1); //q + 1 = 0x7fff50160bf4 printf("sizeof(char)=%ld\n", sizeof(char)); //1 printf("sizeof(int)=%ld\n", sizeof(int)); //4 /* 指针的计算: 在指针上加1,是移到下一个单元,给实际的指针值加上sizeof类型的值 两个指针相减,值是两个指针的差除以sizeof类型的值 */ // *p -> ac[0] // *(p+1) -> ac[1] // *(p+n) -> ac[n] // 加1如果不加上sizeof(类型)的值,得到的其实并不是我们想要的 // 给指针加1表示要让指针指向下一个变量: // int a[10]; // int *p = a; // *(p+1) -> a[1]; // 如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义 /* 指针计算: 给指针加减一个整数(+, +=, -, -=) 递增递减(++/--) 两个指针相减:值是有几个sizeof类型的值存在 */ while(*p!=-1) { printf("%d\n", *p++); } /* *p++ 取出p所指的那个数据,顺便把p移到下一个位置去 *的优先级虽然高,但是没有++高 常用于数组类的连续空间操作 在某些cpu指令上,这可以直接被翻译成一条汇编指令 */ /* 指针比较: <, <=, ==, >, >=, != 都可以对指针做 比较他们在内存中的地址 数组中的单元的地址肯定是线性递增的 */ /* 0地址: 当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址 所以你的指针不应该具有0值 因此可以用0地址来表示特殊的事情 返回的指针是无效的 指针没有被真正初始化(先初始化为0) NULL是一个预定义的符号,表示0地址,有些编译器不识别小些的null 有的编译器不愿意你用0来表示0地址 */ /* 指针的类型: 无论指向什么类型,所有的指针的大小都是一样的,因为都是地址 但是指向不同类型的指针是不能直接互相赋值的 这是为了避免用错指针 */ /* 指针的类型转换: void* 表示不知道指向什么东西的指针 计算时与char* 相同(但不相通) 指针也可以转换类型 int *p = &i; void *q = (void*)p;//通过p看i是一个int,通过q看i是一个void(强制类型转换后赋给q) 这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量 不再当你是int,而认为是void */ /* 用指针来做什么: 需要传入较大的数据时用作参数 传入数组后对数组做操作 函数返回不止一个结果 需要用函数来修改不止一个变量 动态申请的内存 */ return 0; }
动态内存分配: // main.c // Created by weichen on 15/6/10. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> #include <stdlib.h> int main(int argc, const char * argv[]) { /* 动态内存分配 输入数据:输入数据时,先告诉你个数,然后再输入,要记录每个数据 C99可以用变量做数组定义的大小,C99之前呢?int *a = (int*)malloc(n*sizeof(int)); #include <stdlib.h> void* malloc(size_t size); 1. 向malloc申请的空间的大小是以字节为单位的 2. 返回的结果是void*,需要类型转换为自己需要的类型 3. (int*)malloc(n*sizeof(int)); */ int number; int* a; int i; printf("输入数量:"); scanf("%d", &number); // int a[number]; // C99写法 a = (int*)malloc(number*sizeof(int)); //malloc返回的void*,所以需要类型转换一下,现在a就可以当做数组使用 for (i=0; i<number; i++) { scanf("%d", &a[i]); } for (i=number; i>=0; i--) { printf("%d", a[i]); } free(a); // 归还内存 return 0; }
/**
字符串操作: /** * main.c */ #include <stdio.h> int main(int argc, const char * argv[]) { /* 单字符输入输出: putchar,getchar int putchar(int c); 向标准输出写一个字符 返回写了几个字符,EOF (-1)表示写失败(end of file) int getchar(void); 从标准输入读入一个字符 返回类型是int是为了返回EOF (-1):Windows->Ctrl-Z Unix->Ctrl-D */ int ch; while( (ch = getchar()) != EOF ) { putchar(ch); } return 0; /* 字符串数组: char **a; a是一个指针,指向另一个指针,那个指针指向一个字符(串) char a[][1]; */ }
字符串函数实现: // main.c // Created by weichen on 15/6/23. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> #include <string.h>
// main.c // Created by weichen on 15/6/23. // Copyright (c) 2015年 weichen. All rights reserved.
// main.c // Created by weichen on 15/6/23. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h>
// main.c // Created by weichen on 15/6/26. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, const char * argv[]) { /* 在字符串中找单个字符 char* strchr(const char *s, int c); char* strrchr(const char *s, int c); 返回NULL表示没有找到 */ char s[] = "hello"; char *p = strchr(s, 'l'); printf("%s\n", p); //llo //找第二个l char *q = strchr(p + 1, 'l'); printf("%s\n", q); //lo //从右边开始找 char *a = strrchr(s, 'l'); printf("%s\n", a); //lo //复制找到的字符串 char *r = (char*)malloc(strlen(p) + 1); //1.动态分配内存空间 char *t = strcpy(r, p); //2.复制字符串 printf("%s\n", t); //llo free(r); //3.释放动态分配的内存空间 //找l之前字符的技巧 char c = *p; *p = '\0'; //将*p所指的位置替换为\0; s就变成了he\0lo char *u = (char*)malloc(strlen(s) + 1); char *v = strcpy(u, s); printf("%s\n", v); //he printf("%s\n", s); //he free(u); //最后将*p恢复为l *p = c; printf("%s\n", s); //hello /* 字符串中找字符串 char* strstr(const char *s1, const char *s2); 字符串中找字符串,并忽略大小写 char* strcasestr(const char *s1, const char *s2); */ char x[] = "E"; char y[] = "e"; char *z1 = strstr(s, x); //如果第二个参数x改为字符'E',就会报错,因为函数接受的参数是一个指针; char *z2 = strstr(s, y); char *z3 = strcasestr(s, x); printf("%s\n", z1); //null printf("%s\n", z2); //ello printf("%s\n", z3); //ello /* 连接两个字符串 extern char* strcat(char *dest, char *src); */ char ab[10] = "good"; char *cd = "bye"; strcat(ab, cd); printf("%s\n", ab); //goodbye return 0; } //注:PHP中strchr是strstr的别名,因为里面没有指针一说,所以第一第二个参数均为字符串。
Refer:C语言指针的重要性 Link:http://www.cnblogs.com/farwish/p/4477897.html |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论