精华内容
下载资源
问答
  • c语言数组越界
    2021-05-20 12:54:51

    详详解解C语语言言数数组组越越界界及及其其避避免免方方法法

    所谓的数组越界,简单地讲就是指数组下标变量的取值 过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外

    ,这类错误也是 C 语言程序中最常见的错误之一。

    在 C 语言中,数组必须是静态的。换而言之,数组的大小必须在程序运行前就确定下来。由于 C 语言并不具有类似 Java 等语

    言中现有的静态分析工具的功能,可以对程序中数组下标取值范围进行严格检查,一旦发现数组上溢或下溢,都会因抛出异常而

    终止程序。也就是说,C 语言并不检验数组边界,数组的两端都有可能越界,从而使其他变量的数据甚至程序代码被破坏。

    因此,数组下标的取值范围只能预先推断一个值来确定数组的维数,而检验数组的边界是程序员的职责。

    一般情况下,数组的越界错误主要包括两种:数组下标取值越界与指向数组的指针的指向范围越界。

    数数组组下下标标取取值值越越界界

    数组下标取值越界主要是指访问数组的时候,下标的取值不在已定义好的数组的取值范围内,而访问的是无法获取的内存地址。

    例如,对于数组 int a[3],它的下标取值范围是 [0 ,2] (即 a[0]、a[1] 与 a[2])。如果我们的取值不在这个范围内 (如 a[3])

    ,就会发生越界错误。示例代码如下所示:

    int a[3];

    int i=0;

    for(i=0;i<4;i++)

    {

    a[i] = i;

    }

    for(i=0;i<4;i++)

    {

    printf("a[%d]=%d\n",i,a[i]);

    }

    很显然,在上面的示例程序中,访问 a[3] 是非法的,将会发生越界错误。因此,我们应该将上面的代码修改成如下形式:

    int a[3];

    int i=0;

    for(i=0;i<3;i++)

    {

    a[i] = i;

    }

    for(i=0;i<3;i++)

    {

    printf("a[%d]=%d\n",i,a[i]);

    }

    指指向向数数组组的的指指针针的的指指向向范范围围越越界界

    指向数组的指针的指向范围越界是指定义数组时会返回一个指向第一个变量的头指针,对这个指针进行加减运算可以向前或向后

    移动这个指针,进而访问数组中所有的变量。但在移动指针时,如果不注意移动的次数和位置,会使指针指向数组以外的位置,

    导致数组发生越界错误。下面的示例代码就是移动指针时没有考虑到移动的次数和数组的范围,从而使程序访问了数组以外的存

    储单元。

    int i;

    int *p;

    int a[5];

    /*数组a的头指针赋值给指针p*/

    p=a;

    for(i=0;i<10;i++)

    {

    /*指针p指向的变量*/

    *p=i+10;

    /*指针p下一个变量*/

    p++;

    }

    在上面的示例代码中,for 循环会使指针 p 向后移动 10 次,并且每次向指针指向的单元赋值。但是,这里数组 a 的下标取值范

    围是 [0 ,4] (即 a[0]、a[1]、a[2]、a[3] 与 a[4])。因此,后 5 次的操作会对未知的内存区域赋值,而这种向内存未知区域赋

    值的操作会使系统发生错误。正确的操作应该是指针移动的次数与数组中的变量个数相同,如下面的代码所示:

    int i;

    int *p;

    int a[5];

    /*数组a的头指针赋值给指针p*/

    p=a;

    for(i=0;i<5;i++)

    {

    /*指针p指向的变量*/

    *p=i+10;

    /*指针p下一个变量*/

    p++;

    }

    为了加深大家对数组越界的了解,下面通过一段完整的数组越界示例来演示编程中数组越界将会导致哪些问题。

    define PASSWORD "123456"

    int Test(char *str)

    {

    更多相关内容
  • C语言数组越界问题

    2022-05-22 00:15:47
    数组越界获取到的值. 因为越界后,获取到的值是按照存储的先后,先存入的则地址高,后存入的则地址低. 数组越界后,如果你越界了那么会获取到地址高的值. 所以在C语言当中对数组越界方面,要十分注意. 如果越界...

    越界问题:

    数组越界获取到的值.

    因为越界后,获取到的值是按照存储的先后,先存入的则地址高,后存入的则地址低.

    数组越界后,如果你越界了那么会获取到地址高的值.

    所以在C语言当中对数组越界方面,要十分注意.

    如果越界问题,从上面所说,获取到的是高地址.

    那么需要注意的一点,C语言对于for、while、switch等一些语句写进栈会有不一样的情况.

    如果要真正的理解,需要看汇编以及一些存储问题.

    那么用一个大概的想法.

    以下是数组越界获取到的值的想法.

    第一:获取到的就是一些垃圾值.(比如你注释的一些内容等),对于注释方面,需要注意!!

    我会在下面让他体现一些关于注释和不注释的区别.

    第二:获取到的就是一些你之前定义的变量.(比如你在数组定义之前定义了一些变量)

    如图所示:

    我先定义了数组,长度为10,再次定义了一个变量i = 100,然后打印i的值,因为在没有受到一些越界影响的问题的时候,我i = 100,然后进入循环当中,我在for循环里面定义了int i = 0,这个没想错的话应该是局部变量,不会影响到外部的i变量,然后i = 0,然后循环15次,分别把xint数组所有的值,进行遍历打印出来.

    嗯,上面就是这些代码没有越界的情况下所进行的过程.

    在说下面问题之前,我先说说大概的一些,这个只是给你一个大概的模型,并没有全部给概括进去.

    因为存储方式是以栈的形式,那么按照我的想法,我先定义一个长度为10数组xint,然后再次定义i = 100,嗯,那么按照我的想法,既然我是以栈的形式存入,我按照先定义先定义先存入,这个想法好像在对一些语句是不对的,因为你可以尝试一下,我在数组前面定义变量i,按照我的编译器还是能获取到的.

    嗯,先不说这个话题

    如果按照我的想法走,因为先定义先存入,那么我数组如果越界了,那么获取到的就是高地址,数组是后存入的,那么我越界获取到的可能会有你之前定义的变量,也会有一些垃圾值,对于垃圾值,我上面大概说了一些,应该没问题.

    然后,因为我数组长度为10,如果我数组xint[10]即为越界到了高地址,那么按照我之前的想法获取到的值,就是i = 100的值。

    如图所示:

     

    这个是我运行后的结果.

    我在越界到xint[10]的时候获取到的值为100,你是不是以为我上面的想法一定是对的?

    嘿嘿,这个是在没有注释for循环语句的时候,才是这样.

    那么我注释for循环语句,那么我越界到10获取到的,还是不是100呢?

     

    我在注释掉for循环后,我越界到11才获取到100.

     

    这里面,我没有注释第二个for循环语句

    如图所示:

    数组越界到13才获取到100.

    这里如果我对数组xint[13]进行赋值,那么会把之前的值给修改掉,会导致你的结果出错或者造成死循环.

    运行结果图:

    这就是导致你死循环甚至出现报错问题的原因.

    至于我在for循环()里面对于定义int i = 0和i = 0的区别,在于局部和全局变量.

    想不明白为什么有时候是越界到10或者11或者13.

    如果我理解错了,求求求了,告诉我

    展开全文
  • 关注、星标公众号,直达精彩内容ID:技术让梦想更伟大作者:李肖遥所谓的数组越界,简单地讲就是指数组下标变量的取值超过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外,这类错误...

    关注、星标公众号,直达精彩内容

    ID:技术让梦想更伟大

    作者:李肖遥

    所谓的数组越界,简单地讲就是指数组下标变量的取值超过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外,这类错误也是 C 语言程序中最常见的错误之一。

    在 C 语言中,数组必须是静态的。换而言之,数组的大小必须在程序运行前就确定下来。由于 C 语言并不具有类似 Java 等语言中现有的静态分析工具的功能,可以对程序中数组下标取值范围进行严格检查,一旦发现数组上溢或下溢,都会因抛出异常而终止程序。也就是说,C 语言并不检验数组边界,数组的两端都有可能越界,从而使其他变量的数据甚至程序代码被破坏。

    因此,数组下标的取值范围只能预先推断一个值来确定数组的维数,而检验数组的边界是程序员的职责。

    一般情况下,数组的越界错误主要包括两种:数组下标取值越界与指向数组的指针的指向范围越界

    数组下标取值越界

    数组下标取值越界主要是指访问数组的时候,下标的取值不在已定义好的数组的取值范围内,而访问的是无法获取的内存地址。例如,对于数组 int a[3],它的下标取值范围是[0,2](即a[0]、a[1] 与 a[2])。如果我们的取值不在这个范围内(如 a[3]),就会发生越界错误。示例代码如下所示:

     1int a[3];
     2int i=0;
     3for(i=0;i<4;i++)
     4{
     5    a[i] = i;
     6}
     7for(i=0;i<4;i++)
     8{
     9    printf("a[%d]=%d\n",i,a[i]);
    10}
    

    很显然,在上面的示例程序中,访问 a[3] 是非法的,将会发生越界错误。因此,我们应该将上面的代码修改成如下形式:

     1int a[3];
     2int i=0;
     3for(i=0;i<3;i++)
     4{
     5    a[i] = i;
     6}
     7for(i=0;i<3;i++)
     8{
     9    printf("a[%d]=%d\n",i,a[i]);
    10}
    

    指向数组的指针的指向范围越界

    指向数组的指针的指向范围越界是指定义数组时会返回一个指向第一个变量的头指针,对这个指针进行加减运算可以向前或向后移动这个指针,进而访问数组中所有的变量。但在移动指针时,如果不注意移动的次数和位置,会使指针指向数组以外的位置,导致数组发生越界错误。下面的示例代码就是移动指针时没有考虑到移动的次数和数组的范围,从而使程序访问了数组以外的存储单元。

     1int i;
     2int *p;
     3int a[5];
     4/*数组a的头指针赋值给指针p*/
     5p=a;
     6for(i=0;i<10;i++)
     7{
     8    /*指针p指向的变量*/
     9    *p=i+10;
    10    /*指针p下一个变量*/
    11    p++;
    12}
    

    在上面的示例代码中,for 循环会使指针 p 向后移动 10 次,并且每次向指针指向的单元赋值。但是,这里数组 a 的下标取值范围是 [0,4](即 a[0]、a[1]、a[2]、a[3] 与 a[4])。因此,后 5 次的操作会对未知的内存区域赋值,而这种向内存未知区域赋值的操作会使系统发生错误。正确的操作应该是指针移动的次数与数组中的变量个数相同,如下面的代码所示:

     1int i;
     2int *p;
     3int a[5];
     4/*数组a的头指针赋值给指针p*/
     5p=a;
     6for(i=0;i<5;i++)
     7{
     8    /*指针p指向的变量*/
     9    *p=i+10;
    10    /*指针p下一个变量*/
    11    p++;
    12}
    

    为了加深大家对数组越界的了解,下面通过一段完整的数组越界示例来演示编程中数组越界将会导致哪些问题。

     1#define PASSWORD "123456"
     2int Test(char *str)
     3{
     4    int flag;
     5    char buffer[7];
     6    flag=strcmp(str,PASSWORD);
     7    strcpy(buffer,str);
     8    return flag;
     9}
    10int main(void)
    11{
    12    int flag=0;
    13    char str[1024];
    14    while(1)
    15    {
    16        printf("请输入密码:  ");
    17        scanf("%s",str);
    18        flag = Test(str);
    19        if(flag)
    20        {
    21            printf("密码错误!\n");
    22        }
    23            else
    24            {
    25                printf("密码正确!\n");
    26            }
    27    }
    28    return 0;
    29}
    

    上面的示例代码模拟了一个密码验证的例子,它将用户输入的密码与宏定义中的密码123456进行比较。很显然,本示例中最大的设计漏洞就在于 Test() 函数中的 strcpy(buffer,str) 调用。

    由于程序将用户输入的字符串原封不动地复制到 Test() 函数的数组 char buffer[7] 中。因此,当用户的输入大于 7 个字符的缓冲区尺寸时,就会发生数组越界错误,这也就是大家所谓的缓冲区溢出Buffer overflow 漏洞。

    但是要注意,如果这个时候我们根据缓冲区溢出发生的具体情况填充缓冲区,不但可以避免程序崩溃,还会影响到程序的执行流程,甚至会让程序去执行缓冲区里的代码。示例运行结果为:

     1请输入密码:12345
     2密码错误!
     3请输入密码:123456
     4密码正确!
     5请输入密码:1234567
     6密码正确!
     7请输入密码:aaaaaaa
     8密码正确!
     9请输入密码:0123456
    10密码错误!
    11请输入密码:
    

    在示例代码中,flag 变量实际上是一个标志变量,其值将决定着程序是进入密码错误的流程(非 0)还是“密码正确”的流程(0)。当我们输入错误的字符串1234567或者aaaaaaa,程序也都会输出“密码正确”。但在输入0123456的时候,程序却输出“密码错误”,这究竟是为什么呢?

    其实,原因很简单。当调用 Test() 函数时,系统将会给它分配一片连续的内存空间,而变量 char buffer[7]int flag 将会紧挨着进行存储,用户输入的字符串将会被复制进 buffer[7] 中。如果这个时候,我们输入的字符串数量超过 6 个(注意,有字符串截断符也算一个),那么超出的部分将破坏掉与它紧邻着的 flag 变量的内容。

    当输入的密码不是宏定义的123456时,字符串比较将返回 1 或 -1。我们都知道,内存中的数据按照 4 字节(DWORD)逆序存储,所以当 flag 为 1 时,在内存中存储的是0x01000000。如果我们输入包含 7 个字符的错误密码,如aaaaaaa,那么字符串截断符 0x00 将写入 flag 变量,这样溢出数组的一个字节 0x00 将恰好把逆序存放的 flag 变量改为 0x00000000。在函数返回后,一旦 main 函数的 flag 为 0,就会输出“密码正确”。这样,我们就用错误的密码得到了正确密码的运行效果。

    而对于0123456,因为在进行字符串的大小比较时,它小于123456,flag的值是 -1,在内存中将按照补码存放负数,所以实际存储的不是 0x01000000 而是 0xffffffff。那么字符串截断后符 0x00 淹没后,变成 0x00ffffff,还是非 0,所以没有进入正确分支。

    其实,本示例只是用一个字节淹没了邻接变量,导致程序进入密码正确的处理流程,使设计的验证功能失效。

    尽量显式地指定数组的边界

    在 C 语言中,为了提高运行效率,给程序员更大的空间,为指针操作带来更多的方便,C 语言内部本身不检查数组下标表达式的取值是否在合法范围内,也不检查指向数组元素的指针是不是移出了数组的合法区域。因此,在编程中使用数组时就必须格外谨慎,在对数组进行读写操作时都应当进行相应的检查,以免对数组的操作超过数组的边界,从而发生缓冲区溢出漏洞。

    要避免程序因数组越界所发生的错误,首先就需要从数组的边界定义开始。尽量显式地指定数组的边界,即使它已经由初始化值列表隐式指定。示例代码如下所示:

    1int a[]={1,2,3,4,5,6,7,8,9,10};
    

    很显然,对于上面的数组 a[],虽然编译器可以根据始化值列表来计算出数组的长度。但是,如果我们显式地指定该数组的长度,例如:

    1int a[10]={1,2,3,4,5,6,7,8,9,10};
    

    它不仅使程序具有更好的可读性,并且大多数编译器在数组长度小于初始化值列表的长度时还会发生相应警告。

    当然,也可以使用宏的形式来显式指定数组的边界(实际上,这也是最常用的指定方法),如下面的代码所示:

    1#define MAX 10
    2…
    3int a[MAX]={1,2,3,4,5,6,7,8,9,10};
    

    除此之外,在 C99 标准中,还允许我们使用单个指示符为数组的两段“分配”空间,如下面的代码所示:

    1int a[MAX]={1,2,3,4,5,[MAX-5]=6,7,8,9,10};
    

    在上面的 a[MAX]数组中,如果 MAX 大于 10,数组中间将用 0 值元素进行填充(填充的个数为 MAX-10,并从 a[5] 开始进行 0 值填充);如果 MAX 小于 10,[MAX-5]之前的 5 个元素(1,2,3,4,5)中将有几个被[MAX-5]之后的 5 个元素(6,7,8,9,10)所覆盖,示例代码如下所示:

     1#define MAX 10
     2#define MAX1 15
     3#define MAX2 6
     4int main(void)
     5{
     6    int a[MAX]={1,2,3,4,5,[MAX-5]=6,7,8,9,10};
     7    int b[MAX1]={1,2,3,4,5,[MAX1-5]=6,7,8,9,10};
     8    int c[MAX2]={1,2,3,4,5,[MAX2-5]=6,7,8,9,10};
     9    int i=0;
    10    int j=0;
    11    int z=0;
    12    printf("a[MAX]:\n");
    13    for(i=0;i<MAX;i++)
    14    {
    15        printf("a[%d]=%d ",i,a[i]);
    16    }
    17    printf("\nb[MAX1]:\n");
    18    for(j=0;j<MAX1;j++)
    19    {
    20        printf("b[%d]=%d ",j,b[j]);
    21    }
    22    printf("\nc[MAX2]:\n");
    23    for(z=0;z<MAX2;z++)
    24    {
    25        printf("c[%d]=%d ",z,c[z]);
    26    }
    27    printf("\n");
    28    return 0;
    29}
    

    运行结果为:

    1a[MAX]:
    2a[0]=1 a[1]=2 a[2]=3 a[3]=4 a[4]=5 a[5]=6 a[6]=7 a[7]=8 a[8]=9 a[9]=10
    3b[MAX1]:
    4b[0]=1 b[1]=2 b[2]=3 b[3]=4 b[4]=5 b[5]=0 b[6]=0 b[7]=0 b[8]=0 b[9]=0 b[10]=6 b[11]=7 b[12]=8 b[13]=9 b[14]=10
    5c[MAX2]:
    6c[0]=1 c[1]=6 c[2]=7 c[3]=8 c[4]=9 c[5]=10
    

    对数组做越界检查,确保索引值位于合法的范围之内

    要避免数组越界,除了上面所阐述的显式指定数组的边界之外,还可以在数组使用之前进行越界检查,检查数组的界限和字符串(也以数组的方式存放)的结束,以保证数组索引值位于合法的范围之内。例如,在写处理数组的函数时,一般应该有一个范围参数;在处理字符串时总检查是否遇到空字符‘\0’。

    来看下面一段代码示例:

     1#define ARRAY_NUM 10
     2int *TestArray(int num,int value)
     3{
     4    int *arr=NULL;
     5    arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
     6    if(arr!=NULL)
     7    {
     8        arr[num]=value;
     9    }
    10    else
    11    {
    12        /*处理arr==NULL*/
    13    }
    14    return arr;
    15}
    

    从上面的int*TestArray(int num,int value)函数中不难看出,其中存在着一个很明显的问题,那就是无法保证 num 参数是否越界(即当num>=ARRAY_NUM的情况)。因此,应该对 num 参数进行越界检查,示例代码如下所示:

     1int *TestArray(int num,int value)
     2{
     3    int *arr=NULL;
     4    /*越界检查(越上界)*/
     5    if(num<ARRAY_NUM)
     6    {
     7        arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
     8        if(arr!=NULL)
     9        {
    10            arr[num]=value;
    11        }
    12        else
    13        {
    14            /*处理arr==NULL*/
    15        }
    16    }
    17    return arr;
    18}
    

    这样通过if(num<ARRAY_NUM)语句进行越界检查,从而保证 num 参数没有越过这个数组的上界。现在看起来,TestArray() 函数应该没什么问题,也不会发生什么越界错误。

    但是,如果仔细检查,TestArray() 函数仍然还存在一个致命的问题,那就是没有检查数组的下界。由于这里的 num 参数类型是 int 类型,因此可能为负数。如果 num 参数所传递的值为负数,将导致在 arr 所引用的内存边界之外进行写入。

    当然,你可以通过向if(num<ARRAY_NUM)语句里面再加一个条件进行测试,如下面的代码所示:

    1if(num>=0&&num<ARRAY_NUM)
    2{
    3}
    

    但是,这样的函数形式对调用者来说是不友好的(由于 int 类型的原因,对调用者来说仍然可以传递负数,至于在函数中怎么处理那是另外一件事情),因此,最佳的解决方案是将 num 参数声明为 size_t 类型,从根本上防止它传递负数,示例代码如下所示:

     1int *TestArray(size_t num,int value)
     2{
     3    int *arr=NULL;
     4    /*越界检查(越上界)*/
     5    if(num<ARRAY_NUM)
     6    {
     7        arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
     8        if(arr!=NULL)
     9        {
    10            arr[num]=value;
    11        }
    12        else
    13        {
    14            /*处理arr==NULL*/
    15        }
    16    }
    17    return arr;
    18}
    

    获取数组的长度时不要对指针应用 sizeof 操作符

    在 C 语言中,sizeof 这个其貌不扬的家伙经常会让无数程序员叫苦连连。同时,它也是各大公司争相选用的面试必备题目。简单地讲,sizeof 是一个单目操作符,不是函数。其作用就是返回一个操作数所占的内存字节数。其中,操作数可以是一个表达式或括在括号内的类型名,操作数的存储大小由操作数的类型来决定。例如,对于数组 int a[5],可以使用sizeof(a)来获取数组的长度,使用sizeof(a[0])来获取数组元素的长度。

    但需要注意的是,sizeof 操作符不能用于函数类型、不完全类型(指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void 类型等)与位字段。例如,以下都是不正确形式:

     1/*若此时max定义为intmax();*/
     2sizeof(max)
     3/*若此时arr定义为char arr[MAX],且MAX未知*/
     4sizeof(arr)
     5/*不能够用于void类型*/
     6sizeof(void)
     7/*不能够用于位字段*/
     8struct S
     9{
    10    unsigned int f1 : 1;
    11    unsigned int f2 : 5;
    12    unsigned int f3 : 12;
    13};
    14sizeof(S.f1);
    

    了解 sizeof 操作符之后,现在来看下面的示例代码:

     1void Init(int arr[])
     2{
     3    size_t i=0;
     4    for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
     5    {
     6        arr[i]=i;
     7    }
     8}
     9int main(void)
    10{
    11    int i=0;
    12    int a[10];
    13    Init(a);
    14    for(i=0;i<10;i++)
    15    {
    16        printf("%d\n",a[i]);
    17    }
    18    return 0;
    19}
    

    从表面看,上面代码的输出结果应该是0,1,2,3,4,5,6,7,8,9,但实际结果却出乎我们的意料,如图 1 所示。

    图 1 示例代码在 VC++2010 中的运行结果

    是什么原因导致这个结果呢?

    很显然,上面的示例代码在void Init(int arr[])函数中接收了一个int arr[]类型的形参,并且在main函数中向它传递一个a[10]实参。同时,在 Init() 函数中通过sizeof(arr)/sizeof(arr[0])来确定这个数组元素的数量和初始化值。

    在这里出现了一个很大问题:由于 arr 参数是一个形参,它是一个指针类型,其结果是sizeof(arr)=sizeof(int*)。在 IA-32 中,sizeof(arr)/sizeof(arr[0])的结果为 1。因此,最后的结果如图 1 所示。

    对于上面的示例代码,我们可以通过传入数组的长度的方式来解决这个问题,示例代码如下:

     1void Init(int arr[],size_t arr_len)
     2{
     3    size_t i=0;
     4    for(i=0;i<arr_len;i++)
     5    {
     6        arr[i]=i;
     7    }
     8}
     9int main(void)
    10{
    11    int i=0;
    12    int a[10];
    13    Init(a,10);
    14    for(i=0;i<10;i++)
    15    {
    16        printf("%d\n",a[i]);
    17    }
    18    return 0;
    19}
    

    除此之外,我们还可以通过指针的方式来解决上面的问题,示例代码如下所示:

     1void Init(int (*arr)[10])
     2{
     3    size_t i=0;
     4    for(i=0;i< sizeof(*arr)/sizeof(int);i++)
     5    {
     6        (*arr)[i]=i;
     7    }
     8}
     9int main(void)
    10{
    11    int i=0;
    12    int a[10];
    13    Init(&a);
    14    for(i=0;i<10;i++)
    15    {
    16        printf("%d\n",a[i]);
    17    }
    18    return 0;
    19}
    

    现在,Init() 函数中的 arr 参数是一个指向arr[10]类型的指针。需要特别注意的是,这里绝对不能够使用void Init(int(*arr)[])来声明函数,而是必须指明要传入的数组的大小,否则sizeof(*arr)无法计算。但是在这种情况下,再通过 sizeof 来计算数组大小已经没有意义了,因为此时数组大小已经指定为 10 了。

    
    推荐阅读:
    嵌入式编程专辑Linux 学习专辑C/C++编程专辑
    Qt进阶学习专辑关注微信公众号『技术让梦想更伟大』,后台回复“m”查看更多内容;扫描下方微信,加作者微信进技术交流群,请先自我介绍喔。
    
    展开全文
  • 测试C语言数组越界

    2022-02-08 19:51:05
    #include<stdio.h> int main() { int i =0 ,a[10]; printf(" &i = %d \n",&i); for(i;i<=10;++i) { a[i] = 0; printf("&...当把循环条件改为11时,会出现死循环,因为...

    #include<stdio.h>

    int main()
    {
        int i =0 ,a[10];
        printf(" &i = %d \n",&i);
        for(i;i<=10;++i)
        {
            a[i] = 0;
            printf("&a[%d] = %d \n",i,&a[i]);
        }
        return 0;
    }

     1.在Dev-C++中

     当把循环条件改为11时,会出现死循环,因为a[11]的地址与i的地址相等,所以i的值被赋值为0

     相同的情况在linux也是一样的,

     

    而在visual studio 中不会出现这种情况

     visual studio刚好是避开i的地址,而linux或者Dev-C++则没有,这个时候涉及到栈的相关内容,先去学习了

     

    展开全文
  • 数组越界 C语言数组是静态的,不能自动扩容,当下标小于零或大于等于数组长度时,就发生了越界(Out Of Bounds),访问到数组以外的内存。如果下标小于零,就会发生下限越界(Off Normal Lower);如果下标大于等于...
  • c语言数组越界的避免方法

    千次阅读 2019-09-08 16:27:15
    1、尽量显式地指定数组的边界 #define MAX 10 … int a[MAX]={1,2,3,4,5,6,7,8,9,10}; 在 C99 标准中,还允许我们使用单个指示符为数组的两段“分配”空间,如下面的代码所示: int a[MAX]={1,2,3,4,5,[MAX-5]=6,7...
  • C语言数组越界导致死循环实例解析
  • 主要介绍了浅析C语言编程中的数组越界问题,通过内存空间来讨论其导致的程序崩溃问题,需要的朋友可以参考下
  • 先看一个程序 #include int main() ...当 i = 9时按道理来说数组内元素已经访问完全了,应该不会进行下去,但是却并不是这样的, ...此时的 i 已经到达了10,甚至是12,也...这个问题出现的原因就是因为越界访问!
  • 然后,我脑子一响,突然顿悟发现这个代码的问题所在了,这个数组越界没有越过去,要是越过去了,侵犯了i的领土「 内存地址 」了肯定就死循环了。 代码修改一下 #include "stdio.h" int main() { int a[10] , i; ...
  • 局部变量 i 和 arr 在栈区上被使用,因为栈区的生长方向是高地址向低地址生长,所以栈区是先使用高地址处的空间,后使用低地址处的空间,又因为数组随着下标的增长地址由低向高变化,当越界...
  • 本来就想做个课程内容的Feistel加解密,可是c语言基础太差,整天遇到数组越界连续两个****scanf输入字符串key和paintext时,就发生过,如果没memset这两个属性,后面在makeGroup和generateKey会发生数组越界。...
  • 先来看下面一段代码,数组定义为10个元素,但是访问的是12位,产生了越界 #include<stdio.h> int main() { int i = 0; int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; //创建大小为10的数组 for (i = 0; i <...
  • C语言数组越界问题实例

    千次阅读 2014-09-11 16:22:49
    然后再被用,如果在变量后面会先被用,然后自身增加1,不仅仅是赋值,被数组下标引用的时候也是,不过我似乎遇到了很多坑,一个是自己当初粗心编写测试的时候有误,一个是C语言数组越界问题一直没有考虑。...
  • 1、什么是数组访问越界? 2、访问越界会出现什么结果? 二.数组下标越界案例 三.防止数组下标越界方法 四.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.数组下标越界简介 ...
  • C语言数组越界问题

    千次阅读 2020-07-31 22:27:18
    C语言数组越界问题 越界:超出数组下标的位置进行访问。 数组占用了一段连续的内存空间。然后,我们可以通过指定数组下标来访问这块内存里的不同位置。因此,当你的下标过大时,访问到的内存,就不再是这个数组的...
  • 转自:C语言数组越界了,后果很严重,如何避免?https://www.pinlue.com/article/2020/11/3021/3411379204839.html
  • #define _CRT_SECURE_NO_WARNINGS #include #include int main(void) { int count=1; char number[20]={0}; char *p = number; gets_s(number);... } 运行后c语言数组越界访问 是不gets的问题 如何修改
  • C语言数组越界

    2020-01-19 22:13:01
    数组越界是指:数组定义时有十个元素,那么a[0] -- a[5] 分别对应相应的元素,在程序中如果使用了a[16]那么就超出了原来的数组定义的范围,这就是数组下标越界。 c和c++语言中数组下标越界,编译器是不会检查出错误...
  • C语言数组下标越界

    2021-08-31 23:46:59
    C语言数组越界的严重性在于对数组元素访问及修改的内容存在不确定性。 这类没有预知性的修改会导致无法确定的错误,发生缓冲区泄露漏洞。 这也就是数组越界的严重所在。 代码如下所示: 数组里的下标从0开始。 那么...
  • 1.数组越界,是指访问了超出数组定义的内容。实例:inta[2];数组a定义了2个元素!a[0],a[1]:没有越界。a[2]:越界了!对不对?2.计算机全部的内存,其地址是从小到大排列。还是,已经定义的变量(普通变量,指针...
  • c语言数组越界怎么办Let’s understand first, what is index out of bounds? 首先让我们了解一下 , 什么是索引超出范围? Let suppose you have an array with 5 elements then the array indexing will be ...
  • 数组下标越界和内存溢出简介 二.数组下标越界和内存溢出区别 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.数组下标越界和内存溢出简介 **溢出本义是算术...
  • C语言数组越界的含义

    2016-02-23 06:51:24
    听同学说C语言数组越界会导致出错,我试验了下不会,谁能写一个数组越界出错的例子?
  • C语言数组下标越界访问引发的程序死循环
  • C语言基础 数组越界之后

    千次阅读 2018-10-17 23:48:28
    ----------statr reading---------- 问题发现:数组有着下标从‘0’开始的性质
  • 本篇文章纯属娱乐,没太多技术性的东西。只是我觉得还比较有意思,所以记一下!> 大家请看这样一段代码(工具:VC++6.0):#include int main(int argc, char *argv[]){int i;... i++)/* 这里越界了 */{arr[i] = 0...
  • C语言中字符数组越界会怎样?

    千次阅读 多人点赞 2020-04-14 17:39:27
    我们都知道C语言中的数组是不允许动态调整程度的,所有的数组都必须在声明的时候就指定它的长度,比如: char str[]; 就会报错: [Error] storage size of ‘str’ isn’t known 提示我数组的大小是未知的。事情是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,644
精华内容 14,257
关键字:

c语言数组越界