c语言-9

一、指针概述

1.1 指针相关概念

1> 引入目的:能够从地址的角度,找到内存中的数据,而不是以变量的角度去找,效率较高

2> 指针:就是内存地址编号

3> 指针变量:由于指针这个地址编号很难记忆,我们引入指针变量存储指针

存储地址的变量称为指针变量

4> 指针变量中,指针存储地址,作为一个特殊的数据类型,其大小是固定的 8 字节

1.2 指针变量的定义

1> 定义格式:数据类型 * 指针名;

例如:int * ptr;

2> 指针变量的初始化

1、使用一个相同数据类型的变量的地址为其进行初始化 int num = 520; int * ptr = # //将num的地址赋值个指针变量 ptr //定义一个指针变量ptr,指向num 2、使用一个已经初始化了的指针变量给一个新的指针变量进行初始化 int * qtr = ptr; //此时表示两个指针变量同时存储了num的地址 int *qtr = # 3、使用地址的0 就是 NULL为其初始化 int *wtr = NULL; 4、注意:没有初始化的指针变量不能直接使用,因为该指针变量中存储了一个随机地址,如果对其进行更改,可能会导致系统瘫痪 5、野指针:指向非法内存的指针称为野指针 产生情况: 1)定义指针时,没有为其进行初始化 2) 指向了一个内存空间,但是随着程序的进行,该内存空间被回收了,那么该指针也是野指针(悬空指针) 3) 数组下标越界时,访问的地址也是野指针

3> 指针变量的使用:使用运算符 ‘ * ’来取得指针变量中的值,我们也称该运算为 取值运算

1、指针变量在定义时,*号只是身份的象征,表示该语句定义的是指针变量 2、指针变量使用是,*号表示一个运算,取值运算,就是取得该指针变量指向的内存空间中的值 3、总结一下 * 号在C语言中的用途 1) 表示乘号,是一个双目运算符 2) 定义指针时,是身份的象征,表示定义的是指针变量 3) 使用指针时,是取值运算符,表示取得指针变量指向的内存空间中的值 4、总结一下 & 在C语言中的用途 1) 一个&表示双目运算符 按位 与运算 2) 两个&&表示双目运算符 逻辑 与运算 3) 一个&表示单目运算符 取址运算 5、&与*在指针的方面,互为逆运算 int num = 520; int *ptr = # 1) *&num ==> *(&num) ==> *(ptr) ==> num 2) &*ptr ==> &(*ptr) ==> &(num) ==> ptr 3) *&ptr ==>*(&ptr) ==> *(ptr的二级地址) ==> ptr 4) &*num ==>报错

#include<myhead.h> int main(int argc, const char *argv[]) { int num = 520; printf("num = %d\n", num); //num的值 printf("&num = %p\n", &num); //输出变量的地址 //定义指针变量指向num int *ptr = # //该语句执行后:num <==> *ptr printf("ptr = %p\n", ptr); //得到的是num的地址 //通过ptr获取num的值 printf("*ptr = %d\n", *ptr); //输出的是num的值 //解释解释什么叫等价 num = 1314; printf("*ptr = %d\n", *ptr); //输出的是num的值 *ptr = 999; printf("num = %d\n", num); //num的值 return 0; }

4> 指针的大小与指针的类型之间的关系

不同数据类型的指针所占内存空间都是一样的,都是指针的大小,32位系统下为4字节,64位系统下为 8字节

指针的数据类型存在的意义,不是为了给指针分配内存空间的,而是为了指针偏移使用的

不同类型的指针,在进行指针偏移时,偏移的大小跟指针的数据类型有关

指针每偏移一个单位,内存空间就会偏移一个数据类型大小的字节数

指针指向普通变量时,指针的偏移是没有意义的,但是,指针指向数组时,指针的偏移就有了现实的意义,表示指向上一个元素或者下一个元素的地址

#include<myhead.h> int main(int argc, const char *argv[]) { char value_1 = 'H'; //定义字符数据 short value_2 = 520; //定义短整形数据 int value_3 = 1314; //定义整形数据 double value_4 = 3.14; //定义双精度浮点型数据 //定义指针指向普通变量 char *ptr1 = &value_1; short *ptr2 = &value_2; int * ptr3 = &value_3; double *ptr4 = &value_4; printf("ptr1 = %p\n", ptr1); printf("ptr2 = %p\n", ptr2); printf("ptr3 = %p\n", ptr3); printf("ptr4 = %p\n", ptr4); printf("*************************************\n"); printf("ptr1+1 = %p\n", ptr1+1); printf("ptr2+1 = %p\n", ptr2+1); printf("ptr3+1 = %p\n", ptr3+1); printf("ptr4+1 = %p\n", ptr4+1); return 0; }

5> 指针可以使用的运算

关系运算: == 判断两个指针是否指向同一个内存地址,ptr==NULL,判空指针

数加运算:表示对指针进行偏移

取值运算(*)、取址运算(&)

二、指针指向普通变量作为函数参数

1> 指针作为函数的参数进行数据传递时,不一定是地址传递

作业

1> 使用递归实现 求 n 的 k 次方

2> 使用递归实现 strlen 的功能

3> 使用递归实现汉诺塔问题(君子作业)

4> 定义一个函数将一个字符串从大到小排序

5> 实现一个函数,用于检查一个字符串是否是回文字符串(正序和反序都相同)

6> 使用指针完成判断自己的主机存储多字节整数时,是大端存储还是小端存储

7

1.

#include <stdio.h>

long power(int n, int k) {
    if (k == 0) {
        // 任何非零数字的0次方都是1
        return 1;
    } else if (k > 0) {
        // 递归调用,k减1直到k为0
        return n * power(n, k - 1);
    } else {
        // 如果k为负数,则计算1/n的-k次方
        return 1 / power(n, -k);
    }
}

int main() {
    int a, b;
    printf("请输入数字: ");
    scanf("%d", &a);
    printf("请输入此向米: ");
    scanf("%d", &b);

    long result = power(a, b);
    printf("%d  %d  %ld\n", a, b, result);
    
    return 0;
}

2.

#include <stdio.h>

// 递归函数声明
size_t my_strlen(const char *str);

int main() {
    const char *test_str = "Hello, World!";
    size_t len;

    // 调用递归函数
    len = my_strlen(test_str);

    printf("这个lenth为: %zu\n", len);

    return 0;
}

// 递归函数定义
size_t my_strlen(const char *str) {
    if (*str == '\0') { // 如果遇到字符串结束标志
        return 0; // 返回0
    } else {
        // 递归调用,当前字符后面的所有字符的长度加1
        return 1 + my_strlen(str + 1);
    }
}

3.

#include <stdio.h>

void hanoi(int n, char from_rod, char to_rod, char aux_rod) {
    if (n == 1) {
        // 当只有一个盘子时,直接从起始杆移动到目标杆
        printf("将第1个盘子从杆 %c 移动到杆 %c\n", from_rod, to_rod);
    } else {
        // 递归地将 n-1 个盘子从起始杆移动到辅助杆
        hanoi(n - 1, from_rod, aux_rod, to_rod);
        
        // 将剩下的一个盘子从起始杆移动到目标杆
        printf("将第%d个盘子从杆 %c 移动到杆 %c\n", n, from_rod, to_rod);
        
        // 递归地将 n-1 个盘子从辅助杆移动到目标杆
        hanoi(n - 1, aux_rod, to_rod, from_rod);
    }
}

int main() {
    int n;
    printf("请输入盘子的数量: ");
    scanf("%d", &n);
    
    // 调用汉诺塔函数,A 为起始杆,B 为辅助杆,C 为目标杆
    hanoi(n, 'A', 'C', 'B');
    
    return 0;
}

4

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

void sortStringDesc(char *str) {
    int len = strlen(str);
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - 1 - i; j++) {
            if (str[j] < str[j + 1]) { // 如果当前字符小于下一个字符,则交换位置
                char temp = str[j];
                str[j] = str[j + 1];
                str[j + 1] = temp;
            }
        }
    }
}

int main() {
    char str[] = "hello world";
    printf("原来: %s\n", str);
    sortStringDesc(str);
    printf("从大到小: %s\n", str);
    return 0;
}

6

#include <stdio.h>

union EndianCheck {
    int asInt;
    char asChar[4];
} check;

int main() {
    check.asInt = 0x01020304; // 假设这是一个32位的int

    if (check.asChar[0] == 0x01) {
        printf("大.\n");
    } else if (check.asChar[0] == 0x04) {
        printf("小.\n");
    } else {
        printf("为\n");
    }

    return 0;
}

7

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

#define MAX_LINE_LENGTH 1024
#define MAX_WORDS 100

// 函数声明
int countWords(const char *str);

int main() {
    char line[MAX_LINE_LENGTH];
    int wordCount;

    // 读取一行输入
    fgets(line, MAX_LINE_LENGTH, stdin);

    // 统计单词数量
    wordCount = countWords(line);

    printf("单词数量为: %d\n", wordCount);

    return 0;
}

// 函数定义
int countWords(const char *str) {
    int wordCount = 0;
    int inWord = 0;

    while (*str) {
        if (isalpha(*str)) {
            // 如果当前字符是字母并且之前不在单词内,则开始一个新的单词
            if (!inWord) {
                inWord = 1;
                wordCount++;
            }
        } else {
            // 如果当前字符不是字母并且之前在单词内,则结束单词
            inWord = 0;
        }
        str++;
    }

    return wordCount;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值