Linux第一课:c语言 学习记录day09

五、指针

指针数组

1、定义

        本质是数组,里面存放的是指针,

2、格式

        存储类型  数据类型  *数组名【元素个数】

        int *arr[3];

3、应用

1)用于存放普通变量的地址

Int a = 10, b = 20, c = 30;

int *arr[3] = {&a, &b, &c};

访问 b 的地址:

arr[1]        *(arr+1)

访问 b 的值

*arr[1]        *(*(arr+1))

2)用于存放二维数组的每一行第一个元素的地址(列地址)

        int a[2][3] = {1, 2, 3, 4, 5, 6};

        int *arr[2] = {a[0], a[1]};

        访问 a[1][2] 的地址:

        arr[1]+2        *(arr+1)+2

arr:第一个元素的地址

arr+1:第二个元素的地址

*(arr+1):第二个元素

a[1]:第二个元素,第二行第一列的地址

*(arr+1)+2:第二行第三列的地址

3)用于存放字符串

        char str[32] = "hello";        // 存放的是 hello 的字符串

        char *str_add = "hello";        // 存放的是 hello 字符串的首地址

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

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

        printf("%c %c\n", str[1], *(str_add+1));

 使用指针数组存放字符串

        char *str[3] = {"hello", "world", "wang"};

        打印“world”字符串

        printf("%s\n", str[1]);        // world

        printf("%s\n", *(str+1));        // world

        printf("%s\n", *(str+1)+2);        // rld

        打印‘o’字符

        printf("%c\n", *(*(str+1)+1));        // o

        printf("%c\n", str[1][1]);       

        printf("%c\n", *(str[1]+1));

        字符串写多少都行,没有列数要求,可以当二维数组用,二维数组需要规定列数,指针数组不需要

命令行传参

argv:就是一个指针数组,里面存放的时命令行传递的字符串

argc:表示argv指针数组里面存放的数据的个数,即命令行传递的字符串的个数

六、函数

1、概念

        一个完成特定功能的代码模块

2、三要素

功能        参数        返回值

3、格式

存储类型  数据类型  函数名(参数列表) // 形参

{
        函数体;

        return (返回值);

}

注意:

1)没有参数:参数列表可以省略,或者void

2) 没有返回值:return 不写,数据类型是void

3)有返回值:根据返回值的数据类型定义函数的数据类型

4)定义子函数时:可以直接定义在主函数上面,可以直接使用;如果定义在主函数下面的话,要在主函数上面声明子函数

4、声明函数

数据类型 函数名(参数列表);

5、函数调用

1)没有返回值:直接调用:函数名(参数);// 实参,注意数据类型匹配

2)有返回值:如果需要接收返回值,就要定义一个与返回值相同数据类型的变量;

                如果不需要,就直接调用函数

#include <stdio.h>
void fun1()
{
    printf("hello world\n");
}

void fun2(int a,int b)
{
    printf("a+b=%d\n", a+b);
}

int fun3 (int a, int b)
{
    return a*b;
}

int fun4(int a, int b);

int main(int argc, char const *argv[])
{
    int a = 10;
    int b = 5;
    fun1();
    fun2 ( a, 20);
    printf("%d\n", fun3(a, b));
    int c = fun4 (a, b);
    printf ("%d\n", c);
    return 0;
}

int fun4 (int a, int b)
{
    return a-b;
}

6、函数传参

1)值传递

        单向传递,将实参传递给形参使用,改变形参,实参不会受到影响

#include <stdio.h>

int fun (int num, int sum)
{
    num++;
    sum++;
    return num+sum;
}

int main ()
{
    int a = 3;
    int b = 4;
    int ret = fun (a, b);
    printf("%-4d%-4d%-4d\n", a, b, ret);
    return 0;
}

2)地址传递

        双向传递,在函数中修改形参,实参也会发生变化

#include <stdio.h>

int fun1 (int *num, int *sum)
{
    (*num)++;
    (*sum)++;
    return *num + *sum;
}

int main ()
{
    int a = 3;
    int b = 4;
    int ret = fun1 (&a, &b);
    printf("%-4d%-4d%-4d\n", a, b, ret);
}

3)数组传递

        参数中存在数组的定义,会认为是指针变量,不会是数组

验证:

#include <stdio.h>

int fun2 (char s[32])
{
    s = "hello";
    printf("%d\n", sizeof(s));
}

int main()
{
    char str[32] = "hello";
    fun2(str);
    return 0;
}

如果s是数组,就是32;如果是指针就是8

用的时候可以当成指针变量用,也可以当成数组名用

动态内存开辟(开辟堆区空间)

开辟空间

#include <stdlib.h>

void *malloc(size_t size);

 功能:在堆区开辟空间

参数:size:开辟空间大小(单位:字节)

返回值:成功:开辟空间的首地址

        失败:NULL

释放空间

#include <stdlib.h>

void free(void *ptr);

功能:释放堆区空间

参数:ptr:堆区空间的首地址

返回值:无

free(p);

p = NULL;

示例:

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

int main()
{
    int *p = (int *)malloc(sizeof(int) * 10);
    int *q = p; //p不能移动,一旦移动,释放的时候就找不到了
    // 容错判断
    if (p == NULL)
    {
        printf("开辟失败\n");
        return -1;
    }
    printf("开辟成功\n");
    // 使用堆区空间
    for (int i = 0; i < 10; i++)
    {
        *(p+i) = i;
    }
    // 释放堆区空间
    free (p);
    p = NULL;
    return 0;
}

注意:

1、手动开辟堆空间,要注意内存泄漏,

        当指针指向开辟堆区空间后,又对指针重新赋值,则没有指针指向开辟堆区空间,就会造成内存泄漏

2、使用完堆区空间后及时释放空间

string函数族

1、strcpy 

 #include <string.h>

        char *strcpy(char *dest, const char *src);

功能:实现字符串的复制

参数:dest:目标字符串首地址

                src : 原字符串首地址

       把后面的字符串复制到前面的地址里面

返回值:目标字符串首地址

#include <stdio.h>
#include <string.h>

int main ()
{
    char s[32];
    printf("%s\n", s);
    char a[32] = "hello";
    strcpy (s, a);
    printf("%s\n", s);
    return 0;
}

复制包括\0在内的所有字符,注意越界问题

        char *strncpy(char *dest, const char *src, size_t n);

功能:复制前几个字符

参数:dest:目标字符串首地址

                src : 原字符串首地址

                n:字符个数

返回值:目标字符串首地址

#include <stdio.h>
#include <string.h>

int main ()
{
    char s[32];
    printf("%s\n", s);
    char a[32] = "hello";
    strncpy (s, a, 3);
    printf("%s\n", s);
    return 0;
}

s数组没有初始化,所以复制前3个字符里面没有\0所以打印出来前面是hel后面是乱码,使用时对s数组初始化或部分初始化

#include <stdio.h>
#include <string.h>

int main ()
{
    char s[32] = ”world“;
    printf("%s\n", s);
    char a[32] = "hello";
    strncpy (s, a, 3);
    printf("%s\n", s);
    return 0;
}

部分初始化之后,最终打印出来的结果为复制部分拼接s数组剩余的部分

2、strlen

#include <string.h>

        size_t strlen(const char *s);

 功能:计算字符串的实际长度

参数:s:字符串的首地址

返回值:实际长度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值