Day09

变量作用域

C语言变量作用域

1. 如果是局部变量和全局变量同名,那么在访问变量时候,采用就近原则
   会现在局部变量中寻找,找不到再去全局变量中找
2. 在函数中不能访问其他函数中定义的局部变量
3. 在函数中可以访问全局变量
4. 多个函数可以共享一个全局变量

字符串

  • 基本概念
/*
     * 1. 字符串是什么?
     * 将字符串在一起就是字符串,在C语言中字符串就是一个特殊的数组而已
     *
     * 2. 特殊点:
     *   如果想要用数组来表示字符串,那么数组必须是char类型的,而且最后一个元素
     * 必须是\0
     *
     * 3. 由于字符串比较特殊
     *   所以在C语言中除了可以用字符数组来表示字符串,还可以用""来表示字符串
     *
     */

    char str1[] = {'w', 'j', 'n', '\0'}; //字符串以'\0'结尾
    char str2[] = {'w', 'j', 'n'}; //不是字符串,是字符数组
    //赋值的同时部分初始化,没有初始化的元素会自动赋值为0
    char str3[10] = {'w', 'j', 'n', '\0'};
    chr str4 = "wjh";
    printf("%s\n", str);
  • 字符串内存分析
    //两者在内存中存储的状态
    char str1[] = {'w', 'j', 'n', '\0'}; //字符串
    char str2[] = {'w', 'j', 'n'};  //字符数组
Day09_第1张图片
  • 字符串输出和输入
    字符串输出: puts(str); 字符串输入: gets(ch);
   /*
     * 字符串输出和输入问题
     */


    //1. 字符串输出
    char str[] = "lnj";
    //1.1 printf("%s"),%s会从数组的第0个元素开始打印,直到遇到\0位置
    //    这种输出不会自动换行需要\n,还可以添加自定义内容
    printf("%s\n", str);

    //1.2 puts输出会自动换行,但是不能自定义添加内容
    puts(str);



    //2. 字符串输入
    char ch[10];
    //2.1 scanf("%s", &ch);接收字符串,输入的数据中不能有空格/TAB/回车,系统会将他们默认为结束字符
    //scanf("%s", &ch);
    //printf("%s\n", ch);
    //2.2 gets接收方式
    //    可以输入空格TAB符号
    gets(ch);
    printf("%s\n", ch);
  • 字符串系统函数
    注意点: 使用此类函数必须在头部导入#include
    /*
     * 字符串长度计算 strlen();
     */

    char str[] = "niuzi";
    //注意点: 这种计算字符串长度不包括\0字符,而且还能计算出字符串中存储字符数,但是使用系统函数需要在头部导入#include 
    int len = strlen(str);
    printf("%i\n", len); // 5
#include 
int main()
{
    /*
     * 字符串拼接
     * strcat(ch1,ch2),传入两个数组,会将后面字符串数组拼接到前面
     * 注意点: 前面的数组必须足够长,能够容纳两个
     */
    char str1[10] = "niuzi";
    char str2[] = "wjh";
    strcat(str1, str2);

    printf("%s\n", str1);
    printf("%s\n", str2);
    
    return 0;
}

include 
#include 
void myStrncar(char dest[], char src[], int count);
int main()
{
    /*
     * 字符串拼接
     * strncat(dest, src, count);
     * 会将src中count个字符拼接到dest后面
     */

    char str1[20] = "niuzi";
    char str2[10] = "888666";
    strncat(str1, str2, 2);
    printf("%s\n", str1);
    return 0;
}
    /*
     * 字符串拷贝
     * 会将后面的字符拷贝到前面,覆盖前面原有的内容
     */

    char str1[20] = "wjh";
    char str2[20] = "haha";

    strcpy(str1, str2);
    printf("%s\n", str1);
    /*
     * 字符串比较
     * 会依次从第0个索引开始,取出第一个数组和第二个数组中每个元素
     * 如果str1当前元素大于str2当前元素,那么返回一个正数
     * 如果str1当前元素小于str2当前元素,那么返回一个负数
     * 如果str1当前元素等于str2当前元素,那么返回一个0
     *
     */


    char str1[10] = "124";
    char str2[10] = "124";

    int res = strcmp(str1, str2);
    printf("%i\n", res);

指针

  • 指针变量
    /*
     * 指针变量:
     *    指针变量和普通变量一样,都是用来保存数据的,只不过和普通变量有一点区别
     *    普通变量可以保存基本数据类型,指针变量只能保存内存地址,简言之就是保存内存地址的变量
     * 格式:
     *   数据类型  *变量名称;
     */

    int num = 7;
    int *p; //定义一个指针变量

    //注意点: 所有指针变量占用内存的大小是一样的,与指针数据变量数据类型无关
    //  在32位编译器中,占用4个字节
    //  在64位编译器中,占用8个字节
    //  只要一个变量存储了另外一个变量的内存地址,那么我们可以说这个变量指向了另外一个变量
    //  而且我们可以根据这个内存地址找到另外变量的内存地址,从而操作这部分内存


    p = # // 将num变量占用内存最小的地址存储到指针变量P中
    printf("%p\n", p);
    printf("%p\n", &num);
    printf("%p\n", &p); //取出p自己的地址
  • 指针内存


    Day09_第2张图片
  • 指针变量操作数据

    /*
     * 指针变量操作存储地址数据
     */

    int num = 8;
    int *p;
    p = #
    //1. 只要一个变量指向了另外一个变量,就可以通过*变量名称的方法,操作另外一个变量的内存空间
    *p = 10; //在指针前面加上*号代表访问指针指向的那块内存
    printf("%i\n", num); //10
    
    
    //2. 指针只能保存地址,不能存储其他的值
    //3. 一个变量地址可以被多个指针指向
    //4. 指针的指向可以改变,后赋值的地址会覆盖前面赋值的地址
    //5. 定义指针变量时候,前面的数据类型,一定要和将来保存的变量前面的数据类型一致
    
    int num2 = 10;
    int *p1; // 正确   错误写法: double *p1;
    p1 = &num2;
  • 指针的类型
    注意: 如果函数的形参是数组或者是指针,那么就可以在函数中修改外界传入变量的值
#include 
void change(int *num);
int main()
{
    /*
     * 指针类型:
     *   由于指针变量指向的是某一个变量占用的存储空间的首地址
     *   所以在获取指向变量中存储数据的时候,指针是不知道要获取多少个字节的数据的
     *   所以指针变量的数据类型的作用,就是告诉指针,在获取指向变量的数据时候,需要
     *   获取几个字节的数据
     *
     * int *p 将来获取p指向的那个变量的数据的时候,需要获取4个字节的数据
     */

    int num = 10;
    change(&num); //注意参数如果是指针类型,此处应该传入地址
    printf("%i\n", num); //666
    return 0;
}
//结论: 如果函数的形参是数组或者是指针,那么就可以在函数中修改外界传入变量的值
void change(int *num){
    *num = 666;
}
  • 多级指针
    注意点: 多级指针取值格式: **p,几级指针前面就加几个*
    /*
     * 多级指针:
     *   指针中保存的是其他指针的地址
     * 
     * 如何定义多级指针
     * 在保存的指针变量的基础上加上*即可  int *p --> int **pp
     *
     * 定义指针规则:
     * 1. 将要指向的变量的定义拷贝过来
     * 2. 再将拷贝过来的代码的类型和变量名称中间加上*
     * 3. 修改变量名称
     */

    int num = 10;
    int *p; // 一级指针
    p = #

    int **pp; //二级指针
    pp = &p;

    // **pp -> *p ->num  三个相等
    printf("&num = %p\n", &num);  //0028FEB8
    printf("p = %p\n", p);  //0028FEB8
    printf("&p = %p\n", &p); //0028FEB4 一级指针对应本身的地址
    printf("&pp = %p\n", &pp); //0028FEB0  二级指针对应本身的地址
    printf("pp = %p\n", pp);  //0028FEB4  二级指针存储的是一级指针自身的地址
    printf("*pp = %p\n", *pp); //0028FEB8
    printf("**pp = %i\n", **pp); //10  取出num内存的值


    int ***ppp; //三级指针
    ppp = &pp;
  • 指针与数组
   /*
     * 指针和数组
     *
     * 数组名称保存的就是数组占用内存最小的那个地址
     * 既然数组名称是保存地址,指针也可以保存地址,所以指针也可以指向数组
     *
     * 结论: 如果利用指针保存数组的地址之后,那么p = ages = &ages;
     */

    int ages[3] = {1,3,5};
    printf("%i\n", ages[1]); //3

    int *p;
    p = &ages;
    p[1] = 333;
    printf("%i\n", p[1]); //333
  • 指针加减法
/*
     * 指针加减法
     * 应用场景: 一般都是用在数组中
     * 指针变量+1,加的就是指针变量类型占用的字节数
     * -1操作一般都不会用到
     *
     */
    int arr[3] = {1,3,5};
    int *p = &arr;
    printf("%i\n", *p); // 1  默认指向是数组最小的地址然后取出4个字节
    printf("%i\n", *(p+1)); //3
    printf("%i\n", *(p+2)); //5

    printf("%i\n", *p++); //1
    printf("%i\n", *p++); //3
    printf("%i\n", *p++); //5
  • 指针和字符串
 /*
     * 指针定义字符串
     * 字符串本身就是数组,所以指针也可以定义字符串
     */

//    char str1[] = "hui";
//    //char *str2 = "hui";
//    printf("%s\n", str1);
//    printf("%s\n", str2);

    /*
     * 利用数组和指针定义字符串的区别:
     * 1. 存储位置不同
     *   如果是通过数组定义的字符串,那么存储在内存当中
     *   如果是通过指针定义的字符串,那么存储在内存的常量区中
     * 2.存储空间地址不同
     *   如果是通过数组定义的字符串,每次定义都要重新开辟存储空间
     *   如果是通过指针定义的字符串,重复定义不会重新开辟存储空间
     * 3.由于在内存中存储的位置不一样,所以特性也不一样
     *   如果是通过数组定义的字符串,我们可以手动修改
     *   如果是通过指针定义的字符串,我们不能手动修改
     */

    char *str1 = "lnj";
    char *str2 = "lnj";
    str1[1] = 's'; //不能修改
    printf("%s\n", str1);
//    printf("%p\n", str1); //地址一样
//    printf("%p\n", str2);
int main()
{
    //1. 接收字符串的时候,只能通过字符数组不能通过字符指针
    //2. 学习指针之后,建议将过去传入数组类的形参修改位指针类型
    /*
     * 如果函数中返回的字符串类型是通过数组创建的,那么外界无法获取
     * 如果函数中返回的字符串类型是通过指针创建的,那么外界可以获取
     * 这是因为指针类型存储数组存在常量区当中
     */
    char *str;
    scanf("%s",str); //这种错误
    return 0;
}

void test(int *arr){ //这样方式接收数组类型参数
    
}

char* demo(){
    char *str = "wjh";
    return str;
}
  • 指针变量特点
1. 可以用来保存数据
2. 可以当做形参
3. 可以用来当做返回值

你可能感兴趣的:(Day09)