C语言字符串、指针和内存问题总结

字符串:

字符串变量是字符串的首地址,直到'\0'为止

字符串的表示方式:1  字面值”abc”(字符串常量)

                              2  char *表示

                              3  char s[n]表示

 字符串的操作 

                              

字符串的赋值

   =  改的是地址  strcpy()改的是值   

   char *s1=”abc”  通过 = 赋值操作

   这一句可分解为三部分:

   a 声明;

   b 在只读常量区申请地址存放“abc”;

   c 赋值 

   char s2[4]=”abc”; 

   a 数组可以看作是常指针,不能改指向; 

   b 表示把“abc” 只读常量区内

容赋值到数组 

     等号 = 右边“abc”在只读常量区   

   strcpy(s1,"123"); 通过 strcpy() 赋值操作

   

**********************************************

char* s1 = "abc";  

char s2[4] = "abc"; 

s1 = "123";

//strcpy(s1,"123");  //error 只读区的内容不可以更改

//s2 = "123";    //error 

常指针不能改地址,数组名简单看作常指针不可改变地址,不能做自加自减操作 

char* s3 = malloc(4);

//s3 = "abc";    //error s3 

指向了只读区,堆区内存丢了 ,导致内存泄露

**********************************************

字符串的比较   

  == 比地址    strcmp()  比值

 在只读常量区中  公用相同值的字符串    字符串值相同的只有一份     相同值的字符串地址也相同     

 

  char* s4 = "123"; char* s5 = "123";           //s4 和 s5都在只读存储区

  char s6[4] = "123"; char s7[4] = "123";     // s6 和 s7都是在栈区

  printf("%d\n",s4 == s5);                                //1 比较的是地址  只读存储区中,相同值得字符串地址也相同 

  printf("%d\n",strcmp(s4,s5)==0);                   //1 比较的是值

  printf("%d\n",s7 == s6);                                 //0 比较的是地址

  printf("%d\n",strcmp(s6,s7)==0);                   

//1 

  比较的是值

字符串的拼接   比如拼接文件路径和文件名

  char* name = "dsanmux"; 

  char* path = "/home/user"; 

  char buf[50] = { };            //使用过程中先进行初始化

  sprintf(buf,"%s/%s",path,name);  //sprintf 用于字符串拼接  (字符串拼接方法之一)

  //strcpy(buf,path);  //strcpy和strcat连用完成字符串拼接(字符串拼接方法二) 

  //strcat(buf,"/"); 

  //strcat(buf,name); 

  printf("buf=%s\n",buf); 

用指针操作字符串  比如拆分字符串

 方法一

 char* message = "dsanmux,25"; 

 char mname[20] = { }; 

 char age[10] = { }; 

 int i; 

 for(i=0;*(message+i)!=',';i++); 

 strncpy(mname,message,i); 

 strcpy(age,message+i+1); 


 方法二

 

 int flag = 1; //1代表,之前  遇到,改为0  ;定义一个变量进行状态判断通过给定flag = 1和flag = 0的变化来确定某一个状态的变化,程序中常用 

 int i=0,pos; 

 while(*message)

{     

   if(flag)

   { 

       if(*message==',')

      { 

            flag = 0; 

            pos = i; 

            i++; 

            message++; 

            continue; 

      } 

      mname[i] = *message; 

    }

    else

   { 

         age[i-pos-1] = *message; 

    } 

   i++; 

   message++; 

printf("mname=%s:age=%s\n",mname,age); 


字符串的长度和容量  

 长度:strlen()是数据有多少 

 容量:是sizeof()是 最大能放多少个 ;

 

 char buf1[100] = { }; 

 strcpy(buf1,"123"); 

 printf("length=%d,size=%d\n",strlen(buf1), sizeof(buf1)); 

字符串和int/double之间转换:

 //sprintf()  sscanf() 

  int a1; 

  char buf2[10] = "123"; 

  sscanf(buf2,"%d",&a1);//字符串->int 

  printf("a1=%d\n",a1); 

  char buf3[10] = { }; 

  sprintf(buf3,"%d",a1); 

  printf("buf3=%s\n",buf3); 

指针:

指针是地址
指针变量是变量,是用于存放地址(指针)的变量


内存:

1.函数形参位于栈区,函数gettingspace(str);执行完毕形参将自动释放,从而导致指向(char*)malloc(100);指针释放导致内存泄漏

void gettingspace(char *p_addr)

{

      p_addr = (char*)malloc(100);

}

void test(void)

{

    char  *str = NULL;

    gettingspace(str);

     strcpy(str,"dsanmux");

     printf("%s\n",str);

}

char* gettingspace(void)

{

      char* p_addr = (char*)malloc(100);

     return  

p_addr

}

void test(void)

{

    char  *str = NULL;

    str = gettingspace();

     strcpy(str,"dsanmux");

     printf("%s\n",str);

}

返回指向堆内存的指针是可以的

程序在运行的时候用 malloc 申请任意多少的内存,程序员自己负责在何时用 free释放内存。动态内存的生存期由程序员自己决定,使用非常灵活。


2.返回值返回局部变量地址,gettingspace()执行完毕,栈内存释放,str指向不存在的内存,

如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型

void *gettingspace(void)

{

      char p_addr[] = "dsanmux";   // static char p_addr[] = "dsanmux";   

     return p_addr;

}

void test(void)

{

    char  *str = NULL;

    str = gettingspace();

     printf("%s\n",str);

}

3 .函数形参位于栈区,函数gettingspace(str,100);执行完毕形参将自动释放,从而导致指向(char*)malloc(100);指针释放导致内存泄漏

void gettingspace(char **p_addr,int num)

{

      *p_addr = (char*)malloc(100);

}

void test(void)

{

    char  *str = NULL;

    gettingspace(&str,100);

     strcpy(str,"dsanmux");

     printf("%s\n",str);

}

4.

void test(void)

{

    char  *str = 

(char*)malloc(100);

    gettingspace(str);

    strcpy(str,"dsanmux");

    printf("%s\n",str);

}

5.

char *gettingspace() 


    char *p="dsanmux"; 
    return p; 

int main() 

    char *str; 
    str=returnStr(); 
    printf("%s\n", str); 
    return 0; 
}

因为"dsanmux"是一个字符串常量,存放在只读数据段,把该字符串常量存放的只读数据段的首地址赋值给了指针,所以returnStr函数退出时,该该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。

6.数组是不能作为函数的返回值的,原因是编译器把数组名认为是局部变量(数组)的地址。返回一个数组一般用返回指向这个数组的指针代替,而且这个指针不能指向一个自动数组,因为函数结束后自动数组被抛弃,但可以返回一个指向静态局部数组的指针,因为静态存储期是从对象定义到程序结束的。

int* gettingspace( void )
{
    static int a[10];
    ........
    return a;


函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。

但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。

因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。

准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值