首页 > 编程语言 >一道编程题引发的C中关于数组、指针的思考

一道编程题引发的C中关于数组、指针的思考

时间:2024-04-27 17:00:11浏览次数:32  
标签:int 编程 内存 数组 sizeof array 指针

7-163 谷歌的招聘

由一道编程题引发的C中关于数组、指针的思考

先来看三种数组定义方式

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

int main(){
    //方式1
    int array_1[4] = {1};

    //方式2,变长数组
    int n2;
    scanf("%d",&n2);
    int array_2[n2]; //使用变长数组
    printf("%d\n",sizeof (arr	ay_2) /  4 );

    //方式3,使用malloc函数动态分配内存
    int m=4;
    int *array_3 = (int*)malloc(m * sizeof(int));
    printf("%d",sizeof (array_3) / 4);
}

这三种都是在C语言中定义数组的方法,但它们在数组大小决定方式、内存分配位置和生命周期等方面有所不同。

  1. 固定大小的数组
    这是最基本的数组定义方式。在这种方式中,数组的大小在编译时就已经确定了。
    这种数组在栈上分配内存,生命周期与其所在的函数相同。当函数返回时,这种数组会自动被销毁。
  2. 变长数组
    在这种方式中,数组的大小是在运行时决定的。这种类型的数组在C99标准中被引入。
    这种数组在栈(Stack)上分配内存,而栈内存的大小通常比堆内存(Heap)小得多。当函数返回时,这种数组会自动被销毁,也就是说,它的生命周期与其所在的函数相同。
    注意,虽然变长数组在C99中被引入,但在C11标准中,它们被转移到了可选功能中(optional feature)。并且,一些编译器(例如GCC)默认允许变长数组,但一些其他编译器(例如Clang)则不允许。因此,使用变长数组的可移植性可能会有问题。
  3. 使用malloc函数动态分配内存
    在这种方式中,数组的大小也是在运行时决定的。但这种数组在堆(Heap)上分配内存,堆内存通常比栈内存大得多。
    这种数组的生命周期直到你显式地调用free函数来释放它为止。这意味着,即使函数返回,这种数组也不会被自动销毁,除非你显式地销毁它。
    使用malloc函数动态分配内存的一个主要优点是,可以在运行时分配大量的内存。但是,需要记住在不再需要数组时释放它,否则可能会导致内存泄漏。

内存泄漏:内存泄漏是一种常见的编程问题,特别是在手动内存管理的编程语言(如C或C++)中。它发生在当程序持续地分配内存但未能相应地释放它时。未被释放的内存块随着时间的推移会累积起来,导致可用内存逐渐减少,这可能会降低程序的性能,甚至导致程序崩溃。
更具体地说,当你在C语言中使用malloc、calloc或realloc函数分配内存时,操作系统会为你的程序分配一块内存。这块内存会一直保留,直到你显式地调用free函数来释放它。如果你忘记了释放这块内存,或者由于错误的程序逻辑而未能释放它,那么这块内存就会“泄漏”,它将无法被程序的其他部分使用,即使程序可能不再需要它。

上述代码存在错误

在第三种方法中。试图通过sizeof (array_3) / 4来获取动态分配数组的长度。
但是,这并不会给出正确的结果,因为array_3是一个指针,sizeof (array_3)将返回指针的大小,而不是它指向的内存块的大小。在大多数系统上,一个指针的大小是8字节(对于64位系统),所以sizeof (array_3) / 4的结果将是2,而不是期望的数组长度。要获取动态分配的数组长度,需要自己保存这个信息。

另外的问题:
第二种方式的array_2不也是一个指针吗,为什么方式二可以正确获取数组大小?

在C语言中,数组名确实可以被看作是一个指向数组首元素的指针。但是,静态数组(包括固定大小的数组和变长数组)和动态数组(由malloc等函数分配的数组)在这方面有一些关键的不同。

对于静态数组(包括方式1和方式2的数组),虽然数组名可以被当作一个指针来使用,但它实际上并不是一个真正的指针。数组名更像是一个指向数组首元素的常量指针,并且编译器知道这个数组的大小。因此,当你在静态数组上使用sizeof运算符时,你会得到整个数组的大小,而不是指针的大小。

但是,对于动态数组(方式3的数组),malloc返回的是一个真正的指针。这个指针指向分配的内存块的首地址,但编译器并不知道这个内存块的大小。因此,在动态数组上使用sizeof运算符时,只会得到指针的大小,而不是整个数组的大小。
这就是为什么可以通过sizeof(array_2) / sizeof(int)来获取方式2的数组的长度,但不能通过sizeof(array_3) / sizeof(int)来获取方式3的数组的长度的原因。在动态分配内存时,需要自己保存数组的长度信息。

image

image

#include <stdio.h>
#include <stdbool.h>
#include <math.h>

bool isPrime(int n){
    if(n == 1) return false;
    for(int i=2;i < n; i++){
        if(n % i == 0){
            return false;
        }
    }
    return true;
}

int main(){
    int n,k,tmp,m=0;
    int num[1000];
    scanf("%d %d",&n, &k);
    //把数据存到数组
    for(int i=0; i<n; i++){
        scanf("%1d",&tmp);
        num[i] = tmp;
    }
    //开始从第i位寻找连续k位素数
    for(int i=0; i<=n-k; i++){
        int account=k-1;
        for(int j=i; j<i+k; j++){   //循环k次,计算数字
            m += num[j] * (int)pow(10,account);
            account--;
        }
        if(isPrime(m)){
            printf("%0*d", k, m);   //*作为宽度指定符
            return 0;
        }
        m=0;    //准备重新寻找
    }
    printf("404");
    return 0;
}
  • printf中,*作为宽度指定符

标签:int,编程,内存,数组,sizeof,array,指针
From: https://www.cnblogs.com/Rainy-Day/p/18162251

相关文章

  • 实验3 C语言函数应用编程
    1.实验任务11#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#include<windows.h>5#defineN8067voidprint_text(intline,intcol,chartext[]);8voidprint_spaces(intn);9voidprint_blank_lines(intn);//函......
  • Python (GUI编程)模块 使用方法
    GraphicalUserInterface,简称GUI,中文名为图形用户界面,又称图形用户接口,是一种通过图形元素(如按钮、文本框、图像等)来与计算机程序进行交互的方式。与传统的命令行界面相比,GUI更加直观和易于使用,因为用户可以直接通过点击、拖拽等方式来完成任务,而无需记忆和输入复杂的命令。GUI......
  • C语言函数编程
    实验1点击查看代码#include<stdio.h>#include<stdlib.h>#include<time.h>#include<windows.h>#defineN80voidprint_text(intline,intcol,chartext[]);//函数声明voidprint_spaces(intn);//函数声明voidprint_blank_lines(intn);/......
  • 实验3 C语言函数应用编程
    实验任务1#include<stdio.h>#include<stdlib.h>#include<time.h>#include<windows.h>#defineN80voidprint_text(intline,intcol,chartext[]);//函数声明voidprint_spaces(intn);//函数声明voidprint_blank_lines(intn);//函数声......
  • 二进制数组
    点击查看代码#读写二进制结构数组fromfunctoolsimportpartialfromstructimportStruct#Writedefwrite_records(records,format,f):"""Writeasequenceoftupletoabinaryfileofstructures"""record_struct=Struct(format)......
  • 面向对象编程
    在面向对象编程的世界里,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为对象,对象可以接收消息,解决问题的方法就是创建对象并向对象发出各种各样的消息;通过消息传递,程序中的多个对象可以协同工作,这样就能构造出复杂的系统并解决现实中的问题面向对象编程:把一组数据和处......
  • 编程心得
    在没进一中信息学竞赛班之前,我并不觉得自己是一个菜鸟,但当我第一次接触它时,我妥协了。。。前面的代码还可以,样例基本都是随便过的,直到学到循环开始,我蒙圈了。什么“for()”“while()”“多重循环”等等等等,让我不知所以然,但也没办法,只能依靠老师和伙伴这么凑活着学。在放寒假的第......
  • 实验3 C语言函数应用编程
    task1.c1#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#include<windows.h>5#defineN8067voidprint_text(intline,intcol,chartext[]);//函数声明8voidprint_spaces(intn);//函数声明9voidpri......
  • 实验3 C语言函数应用编程
    task1#include<time.h>#include<windows.h>#defineN80voidprint_text(intline,intcol,chartext[]);//函数声明voidprint_spaces(intn);//函数声明voidprint_blank_lines(intn);//函数声明intmain(){ intline,col,i; chartext[N]=......
  • 和为 K 的子数组
    Problem:560.和为K的子数组给你一个整数数组nums和一个整数k,请你统计并返回该数组中和为k的子数组的个数。子数组是数组中元素的连续非空序列。示例1:输入:nums=[1,1,1],k=2输出:2示例2:输入:nums=[1,2,3],k=3输出:2思路看了提示使用前缀和配合哈......