stat函数学习引申

来源:互联网 发布:网络诈骗事件 编辑:程序博客网 时间:2024/04/30 08:17

1.指针赋值

   这种赋值方式是错误的 :

     int *a;

     *a=1;

  这种赋值方式才是对的

     int *a;

     int b=10;l

     a=&b;

以上表明:a是一个指针,指向一个int大小的存储空间,而*a表示该空间的内容,如果要想 改变*a的值,只能通过a来完成,不能直接给*a赋值。

   指针a是可以赋值给内存地址比如 a=0x123456,表示,将内存地址123456赋值给int *a,而&b是不能赋值的,这样的赋值:&b=0x123456就是错误的方式,因为,&b不是一个变量,而是一个地址引用,所以不能直接赋值,而a是一个地址指针变量,可以直接赋值

  在a没有被使用的时候,它的值we为nil(空),这也就是在stat函数中使用下面方法会报错的原因:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc,char *argv[]){

        struct stat buf; //以这种方式创建的变量,在创建的时候就已经分配内存了

        if(argc<2){
                printf("./s filename\n");
                exit(1);
        }
        //f(stat(argv[1],*buf)){//这里是以struct stat *buf创建的 *buf,在创建完成后是没有分配内存,值是nil,则会报错 bad address,也就是说,buf地址是空的或者是无效的

         f(stat(argv[1],&buf)){ //以 struct stat buf; 这种方式创建的变量,在创建的时候就已经分配内存了
                perror("stat");
                printf("%s\t%s\t\n",argv[0],argv[1]);
                exit(1);
        }
        printf("%s\t%s\t%ld\n",argv[0],argv[1],buf.st_size);
        return 0;
}
在上面的代码中 报错bad address 的原因:

传递了无效的或者空的地址

所以,使用&buf不会报错而是用*buf就会报错bad address

2.二级指针

    2.1关于main函数参数形式 char *avgv[]  & char **argv

         获取参数可以通过:argv[0] argv[1] 两种形式是定义了指针数组,每一个指针指向一个字符串指针,也就是&argv[i]得到的就是每个指针的地址,argv[i]指向的就是每个字符串

    2.1理解一下int**p  & char **p

        首先p是一个指向一个指针地址(*P)的指针,*p指向一个实际的空间,*p是一个地址,指向一块已经分配了或者即将要分配大小的内存空间,这个内存空间的大小的值是保存在内存中的,和指针本身没有关系,p只是一个指向包含该内存起始地址的指针,举个栗子:

      int a[2][4]={1,2,3,4,5,6,7,8};//对于二维数组,首次要明白一个概念,就算是二维数组在内存中也是以一维的形式存储的,所以,对于二位数组的操作使用一级指针就可以了

下面这种写法就是错误的:

   int **p;

   p=a;//二级指针指向数组a

 printf("%d",(*p)[7]);

会报错,段错误(核心已转移),所以,只有指针变量可以进行地址加减或者[]操作,也就是只能对p[]进行这种操作

当使用printf("%d",*p);输出的结果是  1 而是用printf("p[0]=%d p[1]=%d",p[0],p[1]);输出的结果是:p[0]=1 p[1]=3这是因为:

当使用二级指针指向一个数组的时候,对于64位机来说,一个指针变量的大小为8个字节,其实*p指向的就是数组a的a[0][1] a[0][2]两个空间,因为一个整型占32位,而并不是一个地址,但是在输出的时候,自动截断高位,只输出低32位,对于p[0]来说,也就是输出1,因为2已经丢失了(猜测)。使用**p的时候,会报错:段错误,因为**p没有任何意义,*p里面存的也不是地址,所以,找不到。

   使用p[0]输出的时候会自动找到的是*p里面的内容,而不是**p里面的内容,这是指针的特性,和一级指针一样

    int *q;

   int b[3]={1,2,3};

   q=b;

  当使用p[0]的时候,就会找到*p的内容一样,但是这里需要注意的是(在上面已经提过一次):如果*p里面存的是地址,不能直接对*p进行类似指针一样的操作比如 *p[1] 或者(*p)++ ,只有对指针变量才能进行这样的(p[0]/p++)运算

2.3所以对于char **p来说,p[0]指向的是第一个字符串的首地址,p[1]指向的就是第二个字符串的首地址,比如对于main函数里面使用的char **argc 参数项,我猜测,这里底层中还是要使用malloc()函数对每个传进来的参数进行二级指针的 *argv进行动态的赋值

*argv =(char *)malloc(argc*sizifo(char *));//argv就成为了指针数组

示例:

#include <stdio.h>
#include <stdlib.h>

#define LEN 3

void malloc_a(int **p){

        *p=(int *)malloc(LEN*sizeof(int*));

}

int main(void){

        int *a;
        malloc_a(&a);  
        a[0]=1;
        a[1]=2;
        a[2]=3;
        printf("a0=%d a1=%d a2=%d\n",a[0],a[1],a[2]);
        return 0;
}

示例分析:

int **p :p是一个二级指针也就是说,如果要给p赋值,那么对应的也应该是一个二级指针

int *a: a是一个一级指针,那么对a做取地址运算,也就是&a就可以得到指向int型指针a的地址了,对于&a来说,它现在就相当于一个二级指针

将&a作为形参传递给malloc_a()函数,即 p=&a ,p是一个指针,*p是一个指针的地址,**p是这个指针指向的实际内容,

有*p=a,所以才可以为*p开辟空间,在二级指针的定义上,*p是一个地址,所占的空间大小和指针变量是一样的,

而**p所占的空间就是定义变量类型所决定的了。

0 0