当前位置: 首页 > article >正文

[c语言日寄] 指针学习情况自检题目

在这里插入图片描述

【作者主页】siy2333
【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是进阶开发者,这里都能满足你的需求!
【食用方法】1.根据题目自行尝试 2.查看基础思路完善题解 3.学习拓展算法
【Gitee链接】资源保存在我的Gitee仓库:https://gitee.com/siy2333/study


文章目录

  • 前言
  • 题目引入
  • 知识点分析
    • sizeof 运算符
    • 指针与数组的关系
    • 地址运算
  • 答案
  • 注意事项
    • sizeof 的返回值
    • 指针的大小
    • 数组与指针的区别
    • 地址运算的陷阱
  • 拓展应用
    • 指针与函数
    • 指针与结构体
    • 指针与动态内存分配
    • 指针与字符串
    • 指针与多维数组
  • 总结


前言

在 C 语言的世界里,指针是一种强大而灵活的工具,它允许我们直接操作内存地址。今天,我们就通过一个程序练习来复习指针的使用。


题目引入

#include <stdio.h>

int main() {
    int a[] = {1, 2, 3, 4}; // 内存大小为4 * 4 = 16字节

    printf("%d\n", sizeof(a));
    printf("%d\n", sizeof(a + 0));
    printf("%d\n", sizeof(*a));
    printf("%d\n", sizeof(a + 1));
    printf("%d\n", sizeof(a[1]));
    printf("%d\n", sizeof(&a));
    printf("%d\n", sizeof(*&a));
    printf("%d\n", sizeof(&a[0]));
    printf("%d\n", sizeof(&a[0] + 1));

    return 0;
}

请分析程序的输出结果,并解释每条 printf 语句的含义。
在接下来的文章中,我们会一起把指针的知识与题目结合起来,学习这一知识点。

知识点分析

sizeof 运算符

sizeof 是一个编译时运算符,用于计算变量或数据类型在内存中所占用的字节数。它在处理数组和指针时有一些需要注意的地方。

  • 数组:当 sizeof 的操作数是数组名时,它会返回整个数组占用的字节数。例如,sizeof(a) 返回的是数组 a 的总大小,即 4 * sizeof(int)
  • 指针:当 sizeof 的操作数是指针时,它返回的是指针本身占用的字节数,而不是指针所指向的内容。在 32 位系统中,指针通常占用 4 字节;在 64 位系统中,指针通常占用 8 字节。

指针与数组的关系

在 C 语言中,数组名在大多数情况下可以被视为指向数组首元素的指针。例如,a 可以被视为 &a[0],即数组第一个元素的地址。因此,a + 1 表示数组第二个元素的地址。

  • sizeof(a + 0)a + 0 是数组首元素的地址,sizeof(a + 0) 返回的是指针占用的字节数。
  • sizeof(*a)*a 是数组首元素的值,sizeof(*a) 返回的是数组首元素占用的字节数,即 sizeof(int)
  • sizeof(a + 1)a + 1 是数组第二个元素的地址,sizeof(a + 1) 返回的是指针占用的字节数。
  • sizeof(a[1])a[1] 是数组第二个元素的值,sizeof(a[1]) 返回的是数组第二个元素占用的字节数,即 sizeof(int)

地址运算

在 C 语言中,地址运算符 & 用于获取变量的地址,而解引用运算符 * 用于获取指针所指向的值。

  • sizeof(&a)&a 是整个数组的地址,sizeof(&a) 返回的是指针占用的字节数。
  • sizeof(*&a)&a 是整个数组的地址,*&a 表示整个数组,sizeof(*&a) 返回的是整个数组占用的字节数。
  • sizeof(&a[0])&a[0] 是数组第一个元素的地址,sizeof(&a[0]) 返回的是指针占用的字节数。
  • sizeof(&a[0] + 1)&a[0] + 1 是数组第二个元素的地址,sizeof(&a[0] + 1) 返回的是指针占用的字节数。

答案

#include<stdio.h>

int main() {
    int a[] = {1, 2, 3, 4}; // 内存大小为4*4=16字节

    printf("%d\n", sizeof(a));
    // sizeof()中直接放入数组名,计算整个数组的内存大小:16字节

    printf("%d\n", sizeof(a + 0));
    // 先计算a+0,代表第一个元素的地址,地址在内存中为4/8个字节

    printf("%d\n", sizeof(*a));
    //*a为第一个元素,也就是1,int类型占4字节

    printf("%d\n", sizeof(a + 1));
    // a+1为第二个元素,同上为4字节

    printf("%d\n", sizeof(a[1]));
    // 第二个元素,4字节

    printf("%d\n", sizeof(&a));
    // &a为整个元素的地址,地址就占据4/8个字节

    printf("%d\n", sizeof(*&a));
    // &a表示整个数组的地址,*&a表示整个数组
    // 将数组传入得到数组的大小,即4*4=16字节

    printf("%d\n", sizeof(&a[0]));
    // 第一个元素的地址,地址占4/8字节
    printf("%d\n", sizeof(&a[0] + 1));
    // 第二个元素的地址,4/8字节

    return 0;
}

注意事项

sizeof 的返回值

sizeof 的返回值是 size_t 类型,它是一个无符号整数类型,表示对象的大小。在不同的系统中,size_t 的大小可能不同,但它通常与系统的指针大小一致。因此,在 32 位系统中,size_t 通常占用 4 字节;在 64 位系统中,size_t 通常占用 8 字节。

指针的大小

指针的大小与系统的位数有关。在 32 位系统中,指针占用 4 字节;在 64 位系统中,指针占用 8 字节。因此,sizeof(a + 0)sizeof(&a) 的返回值可能因系统而异。

数组与指针的区别

虽然数组名在大多数情况下可以被视为指针,但数组和指针在某些情况下是有区别的。例如,sizeof(a) 返回的是整个数组的大小,而 sizeof(&a) 返回的是数组的地址占用的字节数。

地址运算的陷阱

在进行地址运算时,需要注意指针的类型和大小。例如,&a[0] + 1 是数组第二个元素的地址,但它的类型是指针,因此 sizeof(&a[0] + 1) 返回的是指针占用的字节数,而不是数组第二个元素的大小。

拓展应用

指针与函数

指针可以作为函数的参数或返回值,这使得函数可以操作内存中的数据。

  • 函数参数:当指针作为函数参数时,函数可以通过指针直接修改调用者的变量。例如,我们可以定义一个函数来交换两个整数的值:
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
  • 函数返回值:函数也可以返回指针,这使得函数可以返回动态分配的内存或数组的地址。例如,我们可以定义一个函数来创建一个动态分配的数组:
int *create_array(int size) {
    int *array = (int *)malloc(size * sizeof(int));
    return array;
}

指针与结构体

指针可以与结构体结合使用,这使得我们可以操作结构体的成员。

  • 结构体指针:我们可以定义一个指向结构体的指针,并通过指针访问结构体的成员。例如:
struct stu {
    int num;
    char name[10];
    int age;
};

struct stu *p = (struct stu *)malloc(sizeof(struct stu));
p->num = 1001;
strcpy(p->name, "Alice");
p->age = 20;
  • 结构体数组指针:我们也可以定义一个指向结构体数组的指针,并通过指针访问结构体数组的元素。例如:
struct stu *p = (struct stu *)malloc(3 * sizeof(struct stu));
p[0].num = 1001;
strcpy(p[0].name, "Alice");
p[0].age = 20;

p[1].num = 1002;
strcpy(p[1].name, "Bob");
p[1].age = 21;

p[2].num = 1003;
strcpy(p[2].name, "Charlie");
p[2].age = 22;

指针与动态内存分配

指针可以用于动态内存分配,这使得我们可以根据需要分配和释放内存。

  • mallocmalloc 函数用于动态分配内存,它返回一个指向分配的内存的指针。例如:
int *array = (int *)malloc(10 * sizeof(int));
  • freefree 函数用于释放动态分配的内存。例如:
free(array);

指针与字符串

指针可以用于处理字符串,这使得我们可以操作字符数组。

  • 字符串指针:我们可以定义一个指向字符串的指针,并通过指针操作字符串。例如:
char *str = "Hello, World!";
printf("%s\n", str);
  • 字符串数组指针:我们也可以定义一个指向字符串数组的指针,并通过指针操作字符串数组。例如:
char *strs[] = {"Hello", "World", "C", "Language"};
printf("%s\n", strs[0]);

指针与多维数组

指针可以用于处理多维数组,这使得我们可以操作多维数组的元素。

  • 二维数组指针:我们可以定义一个指向二维数组的指针,并通过指针操作二维数组的元素。例如:
int array[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p)[3] = array;
printf("%d\n", p[0][1]);
  • 动态分配二维数组:我们也可以动态分配二维数组,并通过指针操作二维数组的元素。例如:
int **array = (int **)malloc(2 * sizeof(int *));
for (int i = 0; i < 2; i++) {
    array[i] = (int *)malloc(3 * sizeof(int));
}
array[0][0] = 1;
array[0][1] = 2;
array[0][2] = 3;
array[1][0] = 4;
array[1][1] = 5;
array[1][2] = 6;
printf("%d\n", array[0][1]);

总结

指针是 C 语言中一个非常重要的概念,它允许我们直接操作内存地址。通过指针,我们可以实现高效的数据操作和复杂的程序功能。在使用指针时,需要注意 sizeof 的返回值、指针的大小、数组与指针的区别以及地址运算的陷阱。此外,指针还可以与函数、结构体、动态内存分配、字符串和多维数组结合使用,实现更强大的功能。希望这篇文章能帮助你更好地理解和使用指针。

关注窝,每三天至少更新一篇优质c语言题目详解~

[专栏链接QwQ] :⌈c语言日寄⌋CSDN
[关注博主ava]:siy2333
感谢观看~ 我们下次再见!!


http://www.kler.cn/a/565605.html

相关文章:

  • 智能指针c/c++
  • 【Groovy】流程控制
  • 三个小时学完vue3 —— 简单案例(二)
  • matlab图论分析之网络构建
  • 实验:k8s+keepalived+nginx+iptables
  • Spine-Leaf和InfiniBand
  • 1.5G 雨晨 22631.4975 IoT 企业版 LTSC 2025 极速精简版
  • GC垃圾回收介绍及GC算法详解
  • 批量将 Word 转换为 PDF/Excel/Txt/图片等多种格式
  • HTML元素,标签到底指的哪块部分?单双标签何时使用?
  • 【R语言】广义加性模型gam
  • 步步为营:用 torch.arange 快速生成数字序列
  • 制氧机分子筛的材质选择与解析‌
  • 【北京迅为】iTOP-RK3568OpenHarmony系统南向驱动开发-第4章 UART基础知识
  • 如何判断邮件列表中邮箱地址的有效性?
  • 【解决】OnTriggerEnter/OnTriggerExit 调用匿名委托误区的问题
  • OpenHarmony分布式软总线子系统
  • 中国生物多样性保护优先区域分布shp数据
  • RabbitMQ系列(五)基本概念之Queue
  • 通过理解 sk_buff 深入掌握 Linux 内核自定义协议族的开发实现