C语言03 - 函数指针内存分配字符串使用
Posted 李樟清
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言03 - 函数指针内存分配字符串使用相关的知识,希望对你有一定的参考价值。
1. 函数指针
int plus(int a, int b)
return a + b;
// 函数名是一个函数的首地址,我已我们可以将函数赋值给对应类型的函数指针
int minus(int a, int b)
return a - b;
int plus2(int *a, int *b)
return *a + *b;
int minus2(char *a, char *b)
return 0;
int main()
int result;
int(*calc)(int a, int b); // 定义了函数指针
//calc = plus;
calc = minus;
result = calc(3,5);
printf("minus : %#x \\n", minus);
printf("result : %d \\n",result); // plus result:8 。 minusresult:-2
// ==========================
int c = 3;
int d = 5;
int(*calc2)(void *a, void *);
calc2 = (int(*)(void *, void *))plus2;// 强制类型转换
result = calc2(&c,&d);
printf("result : %d \\n", result); // result : 8
// void类型的指针:类似java中的object
// 指针变量都是4个字节。都是用十六进制表示。
// void * -> int * / char * / float *
// ==============================================================================
calc2 = (int(*)(void *, void *))minus2;
result = calc2(&c, &d);
printf("result : %d \\n", result); // result : 0
// ==============================================================================
int *p(int a, int b);// 一个返回值是int *的函数,请和函数指针区别开来
system("pause");
return 0;
2. 内存分配
int const num = 100; // 静态变量 静态存储区,不可改变值
void mem()
int *a = (int *)malloc(sizeof(int)* 1024 * 1024); //4M
int main()
// 40M 的数组
// 报错 ,栈溢出:0x00EE1467 处有未经处理的异常(在 JNI_03_VS.exe 中): 0xC00000FD: Stack overflow (参数: 0x00000000, 0x00B82000)。
// int a[1024 * 1024 * 10];
// ==============================================================================
// 在任务管理器可以看到 40.4M ,其中40M是我们开辟的
// 剩下的0.4M 呢?
// 内存:
// 分为3区:
// 程序区
// 程序的二进制文件 (0.4M的由来)
// 静态存储区
// 全局变量和静态变量
// 动态存储区
// 堆区:用于程序动态分配 (比如 malloc)
// 栈区:编译器自动分配,编译器自动申请和释放 2M , 局部变量,
// 自动分配,程序退出自动释放free (比如:int a[1024 * 1024 * 10];
// 预编译阶段,必须确定大小)
// int *a = (int *)malloc(sizeof(int) *1024*1024*10);
// ==============================================================================
// int aa[num];
// int b;
// aa = &b; // 报错,aa的地址是个常量,你能该他的内容,但是不能改他的地址(系统分配的是个常量)
// ==============================================================================
int t = 1000;
int aa[10]; // aa的地址是个常量,你能该他的内容,但是不能改他的地址(系统分配的是个常量)
int ab[100];
/*while (1)
mem();
Sleep(2000);
*/ // 每次都会申请4M。会越来越多
// void* malloc(size_t size)
// 分配内存的单元是 字节, 大小 size,连续的内存
// 如果申请失败,返回值是NULL
// 为什么是void* 呢?
// int *a = (int *)malloc(sizeof(int) *1024*1024*10);
// 如果 a + 1 就是移动了 int 大小的 内存空间
// char *ch = (int *)malloc(sizeof(char) *1024*1024*10);
// ch +1 移动了 char大小的内存空间
int *a = (int *)malloc(sizeof(int)* 1024 * 1024 *500);
if (a == NULL)
// 如果我分配2G(sizeof(int)* 1024 * 1024 *500) ,
// 能进来,但是如果申请更大,为什么不走这里面?
// 因为他已经溢出了,int型数据有一个范围 2的正负32次方
// 比如 1024 * 1024 * 1024 * 100 就已经溢出了
// 溢出了就不去申请了
printf("内存不够,请温柔\\n");
//a[0] = 5; // 报错,因为是空指针
printf("%#x", a);
free(a); // 释放内存,不能重复释放
printf("a address: %#x \\n",&a); // a address: 0x59fb68 ,所以要 =NULL
a = NULL;
// 动态申请的内存一定要收到释放
// free(*p)
// 原则:不能重复释放
// 必须赋值NULL (a 内存释放了,但是指针还是存在的,如果不进行a=NULL,a就是一个野指针)
// if(a!=NULL) ... java GC 虽然标记为释放,但是并没有 及时的释放,所有很多OOM
// 申请和释放一一对应,(使用一次,释放一次)
// ===================================================================
//int *b = (int*)calloc(4, 100 * sizeof(int));
//if (b == NULL)
// printf("内存不够,请温柔\\n");
//
//printf("%#x", b);
// void* calloc(size_t _Count,size_t _Size)
// 申请 _Count 个 大小为_Size 的连续空间,这个连续空间的大小是_Size,
// 而不是 _Count * size, 同时,它会初始化为0
// 如果申请失败,返回值是NULL
system("pause");
return 0;
3. 字符串
// C 语言没有String
// C 语言 用 char* 或char ch[10]表示String
// C 里面,把所有 用 双引号 引起来的 都是放在常量区的,约定俗成的
int main()
char ch1[10] = 'c', 'h','i','n','a';
printf("%s\\n", ch1);
// 在printf里面如果占位符是%s的话,它回去接收一个字符串的首地址
// 从这个地址里面获取所有的字符串,获取到\\0 为止,所以在这个字符串
// 的最后面会有一个 \\0 这个是系统自动加上的空格,以这个空格为结束
// 如下面的代码 ch2
char ch2[10] = 'c', 'h', 'i', 'n', 'a','\\0' ;
printf("%s\\n", ch2);
//char ch1[10] = 'c', 'h','i','n','a','\\0','a'; // 这边打印的 是 china
//char ch1[] = 'c', 'h','i','n','a'; // 这边打印的 是 china加上一些乱码
//char ch1[] = 'c', 'h','i','n','a','\\0' ; // 这种事正常的 打印china
// =================================================================================
// 为什么这样子可以?
// ch3 是常量 ,在这个常量里面他可以存储20个字节的char类型数据
// c语言会把 “china” 这个内存中的内容copy给 ch1 常量所指的空间, 所以我们可以修改ch3[0]的内容
// ch3 是不能被赋值的,因为他是常量,存的是一个地址
char ch3[20] = "china";
// char a;
// ch3 = a;// 报错
ch3[0] = 's';
printf("%s\\n", ch3);
// =================================================================================
char * ch = "zeking";
// ch[2] = 'f'; // 不能修改 ch[2],报错。为什么?
// 因为 ch是一个指针名, zeking是一个常量,当我们赋值给 指针变量的时候
// 这个指针并没有定义空间来存储字符串,所以 编译器就将zeking放到了常量区
// 然后将常量区的首地址赋给了ch,所以ch指向的是一个常量区的地址
// 常量区是不能修改的!所以报错
printf("%#x\\n", ch);
printf("%s\\n", ch);
// ===================================================================================
char * che = (char *)malloc(100 * sizeof(char)); //让che指向一个非常量区
che = "zeking";
//che[2] = 'f'; // 这边还是报错,为什么,因为 把常量区的地址赋给了 che,还存在内存泄漏
// 怎么不内存泄漏呢。在 che = "zeking" 之前 写 free(che); 和 che=NULL;
// ===================================================================================
// 正确的做法
char * che1 = (char *)malloc(100 * sizeof(char));
strcpy(che1, "china"); // 将china常量的内容一一赋值给che1,所以che1还是指向他申请的那片空间
che1[2] = 'f';
printf("%#x\\n", che1);
printf("%s\\n", che1);
// ===================================================================================
system("pause");
return 0;
4. 字符串 案例
char* item32(char * str, char *charSet)
int hash[256];
if (NULL == charSet)
return str;
for (int i = 0; i < 256; i++)
hash[i] = 0;
for (int i = 0; i < strlen(charSet); i++)
hash[charSet[i]] = 1;
int currentIndex = 0;
for (int i = 0; i < strlen(str); i++)
if (!hash[str[i]])
str[currentIndex++] = str[i]; // 这边相当于对 c1 进行了修改,他是常量
str[currentIndex] = '\\0';
return str;
void main()
printf("hello \\n");
//char *c1 = "abcbd"; // 这样是会报错的,形参地址指向的是常量区
// 解决方法1
//char c1[] = "abcbd"; // c1 地址是 stack栈区,保存的是abcbd 字符,自动分配空间,在栈,自动释放
// 解决方法2
char * c1 = (char *)malloc(sizeof(char)* 20);
strcpy(c1, "abcbd");
// char *c1 = "fefe";
char *c2 = "b";
char * s = item32(c1, c2);
printf("%s", s);
system("pause");
5. 字符串api
1. stpcpy :拷贝一个字符串到另一个
函数名: stpcpy
功 能: 拷贝一个字符串到另一个
用 法: char *stpcpy(char *destin, char *source);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char string[10];
char *str1 = "abcdefghi";
stpcpy(string, str1);
printf("%sn", string);
return 0;
2. strcat :字符串拼接函数
函数名: strcat
功 能: 字符串拼接函数
用 法: char *strcat(char *destin, char *source);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char destination[25];
char *blank = " ", *c = "C++", *Borland = "Borland";
strcpy(destination, Borland);
strcat(destination, blank);
strcat(destination, c);
printf("%sn", destination);
return 0;
3. strchr :在一个串中查找给定字符的第一个匹配之处
函数名: strchr
功 能: 在一个串中查找给定字符的第一个匹配之处
用 法: char *strchr(char *str, char c);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char string[15];
char *ptr, c = 'r';
strcpy(string, "This is a string");
ptr = strchr(string, c);
if (ptr)
printf("The character %c is at position: %dn", c, ptr-string);
else
printf("The character was not foundn");
return 0;
4. strcmp : 串比较
函数名: strcmp
功 能: 串比较
用 法: int strcmp(char *str1, char *str2);
看Asic码,str1>str2,返回值 > 0;两串相等,返回0
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *buf1 = "aaa", *buf2 = "bbb", *buf3 = "ccc";
int ptr;
ptr = strcmp(buf2, buf1);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1n");
else
printf("buffer 2 is less than buffer 1n");
ptr = strcmp(buf2, buf3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 3n");
else
printf("buffer 2 is less than buffer 3n");
return 0;
5. strncmpi :将一个串中的一部分与另一个串比较, 不管大小写
函数名: strncmpi
功 能: 将一个串中的一部分与另一个串比较, 不管大小写
用 法: int strncmpi(char *str1, char *str2, unsigned maxlen);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *buf1 = "BBB", *buf2 = "bbb";
int ptr;
ptr = strcmpi(buf2, buf1);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1n");
if (ptr == 0)
printf("buffer 2 equals buffer 1n");
return 0;
6. strcpy :串拷贝
函数名: strcpy
功 能: 串拷贝
用 法: char *strcpy(char *str1, char *str2);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char string[10];
char *str1 = "abcdefghi";
strcpy(string, str1);
printf("%sn", string);
return 0;
7. strcspn :在串中查找第一个给定字符集内容的段
函数名: strcspn
功 能: 在串中查找第一个给定字符集内容的段
用 法: int strcspn(char *str1, char *str2);
程序例:
#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main(void)
char *string1 = "1234567890";
char *string2 = "747DC8";
int length;
length = strcspn(string1, string2);
printf("Character where strings intersect is at position %dn", length);
return 0;
8. strdup :将串拷贝到新建的位置处
函数名: strdup
功 能: 将串拷贝到新建的位置处
用 法: char *strdup(char *str);
程序例:
#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main(void)
char *dup_str, *string = "abcde";
dup_str = strdup(string);
printf("%sn", dup_str);
free(dup_str);
return 0;
9. stricmp : 以大小写不敏感方式比较两个串
函数名: stricmp
功 能: 以大小写不敏感方式比较两个串
用 法: int stricmp(char *str1, char *str2);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *buf1 = "BBB", *buf2 = "bbb";
int ptr;
ptr = stricmp(buf2, buf1);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1n");
if (ptr == 0)
printf("buffer 2 equals buffer 1n");
return 0;
10. strerror :返回指向错误信息字符串的指针
函数名: strerror
功 能: 返回指向错误信息字符串的指针
用 法: char *strerror(int errnum);
程序例:
#include <stdio.h>
#include <errno.h>
int main(void)
char *buffer;
buffer = strerror(errno);
printf("Error: %sn", buffer);
return 0;
11. strcmpi :将一个串与另一个比较, 不管大小写
函数名: strcmpi
功 能: 将一个串与另一个比较, 不管大小写
用 法: int strcmpi(char *str1, char *str2);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *buf1 = "BBB", *buf2 = "bbb";
int ptr;
ptr = strcmpi(buf2, buf1);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1n");
if (ptr == 0)
printf("buffer 2 equals buffer 1n");
return 0;
12. strncmp :串比较
函数名: strncmp
功 能: 串比较
用 法: int strncmp(char *str1, char *str2, int maxlen);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *buf1 = "aaabbb", *buf2 = "bbbccc", *buf3 = "ccc";
int ptr;
ptr = strncmp(buf2,buf1,3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1n");
else
printf("buffer 2 is less than buffer 1n");
ptr = strncmp(buf2,buf3,3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 3n");
else
printf("buffer 2 is less than buffer 3n");
return(0);
13. strncmpi :把串中的一部分与另一串中的一部分比较, 不管大小写
函数名: strncmpi
功 能: 把串中的一部分与另一串中的一部分比较, 不管大小写
用 法: int strncmpi(char *str1, char *str2);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *buf1 = "BBBccc", *buf2 = "bbbccc";
int ptr;
ptr = strncmpi(buf2,buf1,3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1n");
if (ptr == 0)
printf("buffer 2 equals buffer 1n");
return 0;
14. strncpy : 串拷贝
函数名: strncpy
功 能: 串拷贝
用 法: char *strncpy(char *destin, char *source, int maxlen);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char string[10];
char *str1 = "abcdefghi";
strncpy(string, str1, 3);
string[3] = '';
printf("%sn", string);
return 0;
15. strnicmp :不注重大小写地比较两个串
函数名: strnicmp
功 能: 不注重大小写地比较两个串
用 法: int strnicmp(char *str1, char *str2, unsigned maxlen);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *buf1 = "BBBccc", *buf2 = "bbbccc";
int ptr;
ptr = strnicmp(buf2, buf1, 3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1n");
if (ptr == 0)
printf("buffer 2 equals buffer 1n");
return 0;
16. strnset :将一个串中的所有字符都设为指定字符
函数名: strnset
功 能: 将一个串中的所有字符都设为指定字符
用 法: char *strnset(char *str, char ch, unsigned n);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char *string = "abcdefghijklmnopqrstuvwxyz";
char letter = 'x';
printf("string before strnset: %sn", string);
strnset(string, letter, 13);
printf("string after strnset: %sn", string);
return 0;
17. strpbrk :在串中查找给定字符集中的字符
函数名: strpbrk
功 能: 在串中查找给定字符集中的字符
用 法: char *strpbrk(char *str1, char *str2);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char *string1 = "abcdefghijklmnopqrstuvwxyz";
char *string2 = "onm";
char *ptr;
ptr = strpbrk(string1, string2);
if (ptr)
printf("strpbrk found first character: %cn", *ptr);
else
printf("strpbrk didn't find character in setn");
return 0;
18. strrchr :在串中查找指定字符的最后一个出现
函数名: strrchr
功 能: 在串中查找指定字符的最后一个出现
用 法: char *strrchr(char *str, char c);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char string[15];
char *ptr, c = 'r';
strcpy(string, "This is a string");
ptr = strrchr(string, c);
if (ptr)
printf("The character %c is at position: %dn", c, ptr-string);
else
printf("The character was not foundn");
return 0;
19. strrev :串倒转
函数名: strrev
功 能: 串倒转
用 法: char *strrev(char *str);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char *forward = "string";
printf("Before strrev(): %sn", forward);
strrev(forward);
printf("After strrev(): %sn", forward);
return 0;
20. strset :将一个串中的所有字符都设为指定字符
函数名: strset
功 能: 将一个串中的所有字符都设为指定字符
用 法: char *strset(char *str, char c);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char string[10] = "123456789";
char symbol = 'c';
printf("Before strset(): %sn", string);
strset(string, symbol);
printf("After strset(): %sn", string);
return 0;
21. strspn :在串中查找指定字符集的子集的第一次出现
函数名: strspn
功 能: 在串中查找指定字符集的子集的第一次出现
用 法: int strspn(char *str1, char *str2);
程序例:
#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main(void)
char *string1 = "1234567890";
char *string2 = "123DC8";
int length;
length = strspn(string1, string2);
printf("Character where strings differ is at position %dn", length);
return 0;
22. strstr :在串中查找指定字符串的第一次出现
函数名: strstr
功 能: 在串中查找指定字符串的第一次出现
用 法: char *strstr(char *str1, char *str2);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char *str1 = "Borland International", *str2 = "nation", *ptr;
ptr = strstr(str1, str2);
printf("The substring is: %sn", ptr);
return 0;
23. strtod :将字符串转换为double型值
函数名: strtod
功 能: 将字符串转换为double型值
用 法: double strtod(char *str, char **endptr);
程序例:
#include <stdio.h>
#include <stdlib.h>
int main(void)
char input[80], *endptr;
double value;
printf("Enter a floating point number:");
gets(input);
value = strtod(input, &endptr);
printf("The string is %s the number is %lfn", input, value);
return 0;
24. strtok :查找由在第二个串中指定的分界符分隔开的单词
函数名: strtok
功 能: 查找由在第二个串中指定的分界符分隔开的单词
用 法: char *strtok(char *str1, char *str2);
程序例:
#include <string.h>
#include <stdio.h>
int main(void)
char input[16] = "abc,d";
char *p;
/* strtok places a NULL terminator
in front of the token, if found */
p = strtok(input, ",");
if (p) printf("%sn", p);
/* A second call to strtok using a NULL
as the first parameter returns a pointer
to the character following the token */
p = strtok(NULL, ",");
if (p) printf("%sn", p);
return 0;
25. strtol :将串转换为长整数
函数名: strtol
功 能: 将串转换为长整数
用 法: long strtol(char *str, char **endptr, int base);
程序例:
#include <stdlib.h>
#include <stdio.h>
int main(void)
char *string = "87654321", *endptr;
long lnumber;
/* strtol converts string to long integer */
lnumber = strtol(string, &endptr, 10);
printf("string = %s long = %ldn", string, lnumber);
return 0;
26. strupr :将串中的小写字母转换为大写字母
函数名: strupr
功 能: 将串中的小写字母转换为大写字母
用 法: char *strupr(char *str);
程序例:
#include <stdio.h>
#include <string.h>
int main(void)
char *string = "abcdefghijklmnopqrstuvwxyz", *ptr;
/* converts string to upper case characters */
ptr = strupr(string);
printf("%sn", ptr);
return 0;
27. swab :交换字节
函数名: swab
功 能: 交换字节
用 法: void swab (char *from, char *to, int nbytes);
程序例:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char source[15] = "rFna koBlrna d";
char target[15];
int main(void)
swab(source, target, strlen(source));
printf("This is target: %sn", target);
return 0;
PS:isalpha()是字符函数,不是字符串函数,
isalpha
原型:extern int isalpha(int c);
用法:#include
// isalpha.c
#include <syslib.h>
#include <ctype.h>
#include <stdio.h>
main()
int c;
clrscr(); // clear screen
printf("Press a key");
for(;;)
c=getchar();
clrscr();
printf("%c: %s letter",c,isalpha(c)?"is":"not");
return 0; // just to avoid warnings by compiler
以上是关于C语言03 - 函数指针内存分配字符串使用的主要内容,如果未能解决你的问题,请参考以下文章
C 语言二级指针作为输出 ( 指针输入 | 指针输出 | 二级指针 作为 函数形参 使用示例 )
C 语言二级指针案例 ( 字符串切割 | 返回 自定义二级指针 作为结果 | 每个 一级指针 指向不同大小内存 | 精准分配每个 一级指针 指向的内存大小 )