C语言---Day7

16、指针

---windows电脑在数据存储是采用小端对齐

---指针就是内存地址,指针变量是用来存放内存地址的变量;每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址

---在32位操作系统下,所有指针类型都是4个字节大小;   在64位操作系统下,所有指针类型都是8个字节大小

       ---声明指针变量

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */

       ---使用指针:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值;这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值

    int  var = 20;   /* 实际变量的声明 */
    int* ip;        /* 指针变量的声明 */

    ip = &var;  /* 在指针变量中存储 var 的地址 */

    printf("var 变量的地址: %p\n", &var);   // var 变量的地址: 00BDFA20

    /* 在指针变量中存储的地址 */
    printf("ip 变量存储的地址: %p\n", ip);  // ip 变量存储的地址: 00BDFA20

    /* 使用指针访问值 */
    printf("*ip 变量的值: %d\n", *ip);   // *ip 变量的值: 20
// 通过指针间接改变变量的值
int a = 10;
int* p;
p = &a;
*p = 100;
printf("p的值为:%d", *p);

---声明指针变量时,赋值NULL指针;NULL 指针是一个定义在标准库中的值为零的常量

   int  *ptr = NULL;
 
   printf("ptr 的地址是 %p\n", ptr  );  // ptr 的地址是 00000000

---野指针:指针变量指向一个未知的空间;  不要将一个变量的值直接赋值给指针;  操作野指针对应的空间可能会报错,操作空指针对应的空间一定会报错

---万能指针:void* 指针可以指向任意变量的内存空间

    int aa = 10;
    void* po = &aa;
    *(int*)po = 100;
    printf("万能指针在内存占的字节大小: %d\n", sizeof(void*));  // 4
    printf("po值为: %d\n", *(int*)po);

---const修饰的指针

           ---1. const修饰指针类型:可以修改指针变量的值,不可以修改指针指向内存空间的值

    int a = 10, b = 20;
    const int* p = &a;
    printf("%d\n", *p); // 10
    p = &b;
    printf("%d\n", *p); // 20

           ---2. const修饰指针变量:可以修改指针指向内存空间的值,不可以修改指针变量的值

    int a = 10, b = 20;
    int* const p = &a;
    *p = 300;
    printf("%d\n", a); // 300

           ---3. const既修饰指针类型,又修饰指针变量(只读指针):p 中存放的内存单元的地址和内存单元中的内容都不可变

---指针的加法:指针与一个整数相加,整数都会和指针所指向类型的大小(以字节为单位)相乘,然后把结果与初始地址相加

    int m, * n;
    n = &m;
    printf("n为:%d\n", n);   // n为:11533100
    n = n + 2;
    printf("n为:%d\n", n);   // n为:11533108

---指针的减法

    int m1, * n1;
    n1 = &m1;
    printf("n1为:%d\n", n1);   // n为:16710620
    n1 = n1 - 2;
    printf("n1为:%d\n", n1);   // n为:16710612

---递增指针:用指针代替数组,因为变量指针可以递增,而数组不能递增,数组可以看成一个指针常量

    int str[5] = { 100,200,300,400,500 };
    int* ptr;
    ptr = &str[2];
    printf("ptr = %p\n", ptr);  // ptr = 010FF694
    //指针递增
    ptr++;
    printf("ptr = %p\n", ptr);  // ptr = 010FF698

---递减指针:对指针进行递减运算,即把值减去其数据类型的字节数

    int str[5] = { 100,200,300,400,500 };
    int* ptrr;
    ptrr = &str[2];
    printf("ptrr = %p\n", ptrr);  // ptrr = 0133F6F8
    //指针递减
    ptrr--;
    printf("ptrr = %p\n", ptrr);  // ptrr = 0133F6F4

---指针的比较:指针可以用关系运算符进行比较,如 ==、< 和 >;如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较

    int str[5] = { 100,200,300,400,500 };
    int *pt;
    pt = str;
    if (pt <= &str[4])
    {
        printf("pt存储地址小于str[4]的存储地址\n");  // pt存储地址小于str[4]的存储地址
    }
    else
    {
        printf("pt存储地址大于str[4]的存储地址\n");
    }

---指针数组:指针数组是一个数组,其中的每个元素都是指向某种数据类型的指针

            ---指向字符的指针数组来存储一个字符串列表

    const char* names[] = {
                "Zara Ali",
                "Hina Ali",
                "Nuha Ali",
                "Sara Ali",
    };

    for (int i = 0; i < 4; i++)
    {
        printf("Value of names[%d] = %s\n", i, names[i]);  // Value of names[0] = Zara Ali  Value of names[1] = Hina Ali  Value of names[2] = Nuha Ali  Value of names[3] = Sara Ali
    }

            ---指针分别指向不同的整数变量 ,使用指针数组访问整数变量的值

    int num1 = 10, num2 = 20, num3 = 30;

    // 声明一个整数指针数组,包含三个指针
    int* ptrArray[3];

    // 将指针指向不同的整数变量
    ptrArray[0] = &num1;
    ptrArray[1] = &num2;
    ptrArray[2] = &num3;

    // 使用指针数组访问这些整数变量的值
    printf("Value at index 0: %d\n", *ptrArray[0]);  // Value at index 0: 10
    printf("Value at index 1: %d\n", *ptrArray[1]);  // Value at index 1: 20
    printf("Value at index 2: %d\n", *ptrArray[2]);  // Value at index 2: 30

            ---数组指针访问数组中的整数

    int strNum[] = {100,200,300};
    int* pr[3];
    for (int i = 0; i < 3; i++)
    {
        pr[i] = &strNum[i];
        printf("Value of var[%d] = %d\n", i, *pr[i]);  // Value of var[0] = 100  Value of var[1] = 200  Value of var[2] = 300
    }

 ---传递指针给函数

void getSeconds(unsigned long* par);

void getSeconds(unsigned long* par)
{
    *par = time(NULL);
    return;
}

int main()
{
    unsigned long sec;
    getSeconds(&sec);
    printf("Number of seconds: %ld\n", sec);  // Number of seconds: 1705564370
}

---数组指针作为参数

double getAverage(int* arr, int size);
double getAverage(int* arr, int size)
{
    double sum = 0.0;
    for (int i = 0; i < size; i++)
    {
        sum += arr[i];
    }
    double avg = sum / size;
    return avg;
}
int main()
{
    int balance[5] = {1000,2,3,17,50};
    double avg = getAverage(balance, 5);
    printf("Average value is: %f\n", avg);  // Average value is: 214.400000
}

---从函数返回指针:C 语言不支持在调用函数时返回局部变量的地址,除非定义局部变量为 static 变量

int* getRandom();
int* getRandom()
{
    static int  r[10];
    int i;

    /* 设置种子 */
    srand((unsigned)time(NULL));
    for (i = 0; i < 10; ++i)
    {
        r[i] = rand();
        printf("%d\n", r[i]);
    }

    return r;
}

int main()
{
    int* pp;
    pp = getRandom();
    for (int i = 0; i < 10; i++)
    {
        printf("*(pp + [%d]) : %d\n", i, *(pp + i));
    }
}

 ---值传递和地址传递

void swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}

void swap1(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main()
{
    int a = 10;
    int b = 20;

    // 值传递  形参不影响实参的值
    swap(a, b);
    printf("值传递 a的值为:%d\n", a);    // 值传递 a的值为:10
    printf("值传递 b的值为:%d\n", b);   // 值传递 b的值为:20
 
    // 地址传递  形参可以改变实参的值
    swap1(&a, &b);
    printf("地址传递 a的值为:%d\n", a);  // 地址传递 a的值为:20
    printf("地址传递 b的值为:%d\n", b);  // 地址传递 b的值为:10

    return 0;
}

---数组名作为函数参数

// 连接两个字符串
void pointerAs(char* ch1, char* ch2)
{
    while (*ch1) ch1++;
    while (*ch2)
    {
        *ch1 = *ch2;
        ch1++;
        ch2++;
    }
}

int main()
{
    char ch1[100] = "hello ";
    char ch2[] = "world";
    pointerAs(ch1, ch2);
    printf("指针写法:%s\n", ch1); // hello world
}
// 字符串去空格
void strRemoveSpace(char* ch)
{
    char* fTemp = ch;
    char* rTemp = ch;
    while (*fTemp)
    {
        if (*fTemp != ' ')
        {
            *rTemp = *fTemp;
            rTemp++;
        }
        fTemp++;
    }
    *rTemp = 0;
}
int main()
{
    char ch[] = "  h  e  l   l          o w  o r  l d ";
    strRemoveSpace(ch);
    printf("字符串去除空格后为:%s\n", ch);  // helloworld
}

 ---指针作为函数返回值

// 查找字符串的某个字符
char* returnPointer(char* str, char ch)
{
    while (*str)
    {
        if (*str == ch)
        {
            return str;
        }
        str++;
    }
    return NULL;
}
int main()
{
    char str[] = "hello world";
    char* p = returnPointer(str, 'd');
    if (p == NULL)
    {
        printf("未找到\n");
    }
    else
    {
        printf("%s\n",p); // d
    }
    return 0;
}
// 在一个字符串中查找另一个字符串的位置
char* findStr(char* src, char* dest)
{
    char* fsrc = src; // 循环遍历的指针
    char* rsrc = src; // 记录想同的首地址
    char* tdest = dest;
    while (*fsrc)
    {
        rsrc = fsrc;
        while (*fsrc == *tdest && *fsrc != '\0')
        {
            fsrc++;
            tdest++;
        }
        if (*tdest == '\0')
        {
            return rsrc;
        }
        // 回滚
        fsrc = rsrc;
        tdest = dest;
        fsrc++;
    }
    return NULL;
}
int main()
{
    char src[] = "llhello world";
    char dest[] = "llo";

    char* p = findStr(src, dest);
    printf("%s\n", p);  // llo world

    return 0;
}

 

posted @ 2024-01-26 16:18  o·0  阅读(6)  评论(0编辑  收藏  举报