C语言进阶-指针进阶(3)

简介: C语言进阶-指针进阶(3)

9.指针和数组笔试题解析

9.1一维数组

看下面一段代码,分析其打印结果:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  //一维数组
  int a[] = { 1,2,3,4 };
  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 + 1));
  printf("%d\n", sizeof(&a[0]));
  printf("%d\n", sizeof(&a[0] + 1));
  return 0;
}

以上代码大家可以自行运行一下。这里我们只做分析。

在分析之前,再次强调一下对于数组名的理解:

数组名代表数组的首元素的地址。

但是有两个例外:

1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节

2.&(数组名),这里的数组名表示整个数组,取出的是整个数组的地址

下面我们就可以来分析一下代码了:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  //一维数组
  int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));//数组名单独放在sizeof中,计算的整个数组的大小,4*4=16个字节
  printf("%d\n", sizeof(a + 0));//数组名a是数组首元素的地址,a+0还是首元素的地址,地址大小是4/8个字节
  printf("%d\n", sizeof(*a));//*a就是数组首元素,大小是4个字节
  printf("%d\n", sizeof(a + 1));//a是数组首元素地址,a+1是数组第二个元素地址,是地址,大小就是4/8个字节
  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 + 1));//&a+1是跳过整个数组后的地址,是地址,大小就是4/8个字节
  printf("%d\n", sizeof(&a[0]));//数组首元素的地址,大小是4/8个字节
  printf("%d\n", sizeof(&a[0] + 1));//数组第二个元素的地址,大小是4/8个字节
  return 0;
}

注意其中 a+1和&a+1的区别:

a+1:a是数组名,数组名是数组首元素地址,a+1就是数组第二个元素的地址。

&a+1:&a取出的是整个数组的地址,所以&a+1是跳过整个数组之后的地址。

它们在内存中的关系如下图:

9.2字符数组

看下面一段代码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  //字符数组
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", sizeof(arr));//
  printf("%d\n", sizeof(arr + 0));
  printf("%d\n", sizeof(*arr));
  printf("%d\n", sizeof(arr[1]));
  printf("%d\n", sizeof(&arr));
  printf("%d\n", sizeof(&arr + 1));
  printf("%d\n", sizeof(&arr[0] + 1));
  return 0;
}

分析之前首先要知道数组arr中存储的数据是什么:

这段代码和上文中一维数组类似,只不过int型数据是4个字节,char型数据是1个字节:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  //字符数组
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", sizeof(arr));//1*6=6
  printf("%d\n", sizeof(arr + 0));//arr是数组首元素地址,arr+0还是首元素地址,是地址,大小就是4/8个字节
  printf("%d\n", sizeof(*arr));//数组首元素的大小是1个字节
  printf("%d\n", sizeof(arr[1]));//数组第二个元素的大小是1个字节
  printf("%d\n", sizeof(&arr));//&arr取出整个数组的地址,但依然是地址,大小是4/8个字节
  printf("%d\n", sizeof(&arr + 1));//&arr+1是跳过整个数组后的地址,是地址,大小就是4/8个字节
  printf("%d\n", sizeof(&arr[0] + 1));//数组第二个元素的地址,是地址,大小就是4/8个字节
  return 0;
}

接着再看一段代码,我们把上述代码用strlen来计算:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", strlen(arr));//
  printf("%d\n", strlen(arr + 0));
  printf("%d\n", strlen(*arr));
  printf("%d\n", strlen(arr[1]));
  printf("%d\n", strlen(&arr));
  printf("%d\n", strlen(&arr + 1));
  printf("%d\n", strlen(&arr[0] + 1));
  return 0;
}

先来明确一下strlen函数的功能:求字符串长度,统计的是在字符串\0之前的字符的个数,如果没有\0就会一直往后找。

代码分析:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", strlen(arr));//因为字符数组中没有\0,所以strlen函数会一直往后找,直到找到\0,此时打印一个随机值
  printf("%d\n", strlen(arr + 0));//arr+0是首元素地址,所以和第一个一样,还是随机值
  //printf("%d\n", strlen(*arr));//error
  //printf("%d\n", strlen(arr[1]));//error
  printf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,所以strlen还是从数组第一个元素往后找,这里依然是随机值
  printf("%d\n", strlen(&arr + 1));//随机值
  printf("%d\n", strlen(&arr[0] + 1));//随机值
  return 0;
}

注意其中的这两句代码运行时会出现错误:

printf("%d\n", strlen(*arr));
  printf("%d\n", strlen(arr[1]));

原因是strlen函数的参数要求接收的是一个地址,而*arr传给它的是数组首元素‘a’,a的ASCII值是97,所以会将97作为地址传参,此时strlen函数从97这个地址开始统计字符串长度,这就非法访问内存了,此时运行就会报错(如下图)。

通过在www.cplusplus.com中查询strlen函数会发现,strlen函数的参数类型如下:

那这时有人要有疑问了,上图中strlen函数的参数类型是const char*型的,而&arr的类型明明是数组指针 char(*)[6], 那为什么这段代码能运行呢?

printf("%d\n", strlen(&arr));

其实这无关紧要,只要把&arr的值传过去,它就会自然而然变成const char*型,而&arr和arr一个是数组地址,一个是数组首元素地址,但它们的值是一样的, 所以strlen还是从数组第一个元素往后找,这里依然是随机值。

下面我们继续看下一段代码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));
  printf("%d\n", sizeof(arr + 0));
  printf("%d\n", sizeof(*arr));
  printf("%d\n", sizeof(arr[1]));
  printf("%d\n", sizeof(&arr));
  printf("%d\n", sizeof(&arr + 1));
  printf("%d\n", sizeof(&arr[0] + 1));
  printf("%d\n", strlen(arr));
  printf("%d\n", strlen(arr + 0));
  printf("%d\n", strlen(*arr));
  printf("%d\n", strlen(arr[1]));
  printf("%d\n", strlen(&arr));
  printf("%d\n", strlen(&arr + 1));
  printf("%d\n", strlen(&arr[0] + 1));
  return 0;
}

在分析这段代码前,我们先要明确字符数组中存放的内容:

代码分析:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));//7
  printf("%d\n", sizeof(arr + 0));//数组首元素地址,大小是4/8
  printf("%d\n", sizeof(*arr));//数组首元素,大小是1
  printf("%d\n", sizeof(arr[1]));//数组第二个元素,大小是1
  printf("%d\n", sizeof(&arr));//整个数组地址,大小是4/8
  printf("%d\n", sizeof(&arr + 1));//跳过整个数组之后的地址,大小是4/8
  printf("%d\n", sizeof(&arr[0] + 1));//数字第二个元素地址,大小是4/8
  printf("%d\n", strlen(arr));//6
  printf("%d\n", strlen(arr + 0));//数组组首元素地址,往后统计,直到\0,结果是6
  //printf("%d\n", strlen(*arr));//error
  //printf("%d\n", strlen(arr[1]));//error
  printf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,所以strlen还是从数组第一个元素往后找,结果是6
  printf("%d\n", strlen(&arr + 1));//跳过整个数组,同时跳过了\0,往后找是随机值
  printf("%d\n", strlen(&arr[0] + 1));//从数组第二个元素往后找,结果是5
  return 0;
}

注意其中的这代码:

printf("%d\n", strlen(&arr + 1));//跳过整个数组,同时跳过了\0,往后找是随机值

接着看下面一段代码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
  char* p = "abcdef";
  printf("%d\n", sizeof(p));
  printf("%d\n", sizeof(p + 1));
  printf("%d\n", sizeof(*p));
  printf("%d\n", sizeof(p[0]));
  printf("%d\n", sizeof(&p));
  printf("%d\n", sizeof(&p + 1));
  printf("%d\n", sizeof(&p[0] + 1));
  printf("%d\n", strlen(p));
  printf("%d\n", strlen(p + 1));
  printf("%d\n", strlen(*p));
  printf("%d\n", strlen(p[0]));
  printf("%d\n", strlen(&p));
  printf("%d\n", strlen(&p + 1));
  printf("%d\n", strlen(&p[0] + 1));
  return 0;
}

我们前面学过,可以把字符串存放在字符指针中,字符指针变量中存放的是字符串首字符的地址。

代码分析:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
  char* p = "abcdef";
  printf("%d\n", sizeof(p));//p是一个指针变量,大小是4/8
  printf("%d\n", sizeof(p + 1));//p+1是字符'b'的地址,大小是4/8
  printf("%d\n", sizeof(*p));//p中存放的是字符串首字符'a'的地址,*p就是字符'a',大小是1
  printf("%d\n", sizeof(p[0]));//p[0]是字符'a',大小是1
  printf("%d\n", sizeof(&p));//&p的类型是char**,二级指针,大小是4/8
  printf("%d\n", sizeof(&p + 1));//依然是地址,大小是4/8
  printf("%d\n", sizeof(&p[0] + 1));//字符串第二个字符的地址,大小是4/8
  printf("%d\n", strlen(p));//6
  printf("%d\n", strlen(p + 1));//从第二个字符往后统计,是5
  //printf("%d\n", strlen(*p));//error
  //printf("%d\n", strlen(p[0]));//error
  printf("%d\n", strlen(&p));//随机值
  printf("%d\n", strlen(&p + 1));//随机值
  printf("%d\n", strlen(&p[0] + 1));//从第二个字符往后统计,是5
  return 0;
}

注意这两句代码为什么打印出来的是随机值:

printf("%d\n", strlen(&p));//随机值
  printf("%d\n", strlen(&p + 1));//随机值

先来看看他们在内存中的关系图:

由此我们可以看到,p中存放的是字符a的地址,&p就是p这4字节空间中的第一个字节的地址,而&p+1是跳过这4个字节后的地址 ,无论是从&p,还是从&p+1往后统计,我们都不清楚什么时候回遇到\0,所以打印出来的结果是个随机值。

9.3二维数组

接下来的内容有点难了,打起精神哦。

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  //二维数组
  int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));
  printf("%d\n", sizeof(a[0][0]));
  printf("%d\n", sizeof(a[0]));
  printf("%d\n", sizeof(a[0] + 1));
  printf("%d\n", sizeof(*(a[0] + 1)));
  printf("%d\n", sizeof(a + 1));
  printf("%d\n", sizeof(*(a + 1)));
  printf("%d\n", sizeof(&a[0] + 1));
  printf("%d\n", sizeof(*(&a[0] + 1)));
  printf("%d\n", sizeof(*a));
  printf("%d\n", sizeof(a[3]));
  return 0;
}

在这之前,我们先来回顾一些关于二维数组的知识:

 

代码分析:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  //二维数组
  int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));//4*12=48
  printf("%d\n", sizeof(a[0][0]));//4
  printf("%d\n", sizeof(a[0]));//a[0]代表第一行的一维数组的数组名
  //数组名单独放在sizeof内部,sizeof(a[0])计算的是一维数组的大小,大小是16
  printf("%d\n", sizeof(a[0] + 1));
  //a[0]没有单独放在sizeof内部,也没有&
  //a[0]表示数组首元素的地址,也就是a[0][0]的地址
  //a[0]+1就是第一行第二个元素的地址,是地址大小就是4/8
  printf("%d\n", sizeof(*(a[0] + 1)));//*(a[0] + 1)是数组第一行第二个元素,大小是4
  printf("%d\n", sizeof(a + 1));
  //a是二维数组首元素的地址,也就是第一行的地址
  //a+1就是第二行的地址,是地址大小就是4/8
  printf("%d\n", sizeof(*(a + 1)));//*(a+1) -->  a[1],这里计算的是第二行数组的大小,大小是16
  printf("%d\n", sizeof(&a[0] + 1));//&a[0]取出第一行数组的地址,&a[0]+1就是第二行的地址,大小是4/8
  printf("%d\n", sizeof(*(&a[0] + 1)));//第二行的大小,16
  printf("%d\n", sizeof(*a));
  //a是a是二维数组首元素的地址,也就是第一行的地址
  //所以计算的是第一行大小,16
  printf("%d\n", sizeof(a[3]));//16
  return 0;
}

注意这段代码:

printf("%d\n", sizeof(a[3]));//16

有人说,这明显越界访问了呀,为什么还能打印出来16?

因为这里的a[3]它的类型是 int [4],当我们知道这一点的时候,它就不会真的去访问内存,而是直接打印出16,因为在计算机中sizeof计算大小是根据类型来计算的

为了验证sizeof只关注类型,我们用以下代码来证明:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  int a = 3;
  short s = 4;
  printf("%d\n", sizeof(s = a + s));
  printf("%d\n", s);
  return 0;
}

运行结果:

造成这种结果的原因就是:sizeof只关注类型,当我们执行sizeof(s=s+a)时,我们最终的结果会赋给s,而且已经知道了s是短整型,它的大小就是2,此时计算机就不再执行后面的a+s,所以最终s的值没有改变。

10.指针笔试题

笔试题1:

int main()
{
 int a[5] = { 1, 2, 3, 4, 5 };
 int *ptr = (int *)(&a + 1);
 printf( "%d,%d", *(a + 1), *(ptr - 1));
 return 0;
}
//程序的结果是什么?

我们来分析一下:

首先看&a+1,&a取出的是整个数组的地址,那&a+1就是跳过数组之后的地址,此时&a+1的类型是数组指针int(*)[5],通过强制类型转化为(int*),然后将其赋给指针变量ptr,ptr指向的就是跳过数组后的地址,所以*(ptr-1)就是数组最后一个元素5。而*(a+1)是数组第二个元素2。

所以最终的打印结果应该是:2 5。

笔试题2:注意此题是在x86环境下运行的。

//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p=(struct test*)0x100000;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0;
}

注意上述代码中的已知条件,p=0x100000,结构体的大小给出是20个字节。

先来看 p+0x1,p是一个结构体指针,我们讲过,指针的类型决定了指针+-1操作跳过的字节,所以p+0x1跳过20个字节,打印出来的16进制地址是0x100014。

(unsigned long)p现将p的值转换为一个无符号整型数据,此时+0x1,就是在16进制数字0x100000上直接加一,打印出来的应该是0x100001。

(unsigned int*)p将结构体指针p强制类型转换成(unsigned int*),此时进行+1操作跳过4个字节,所以打印结果应该是0x100004。

笔试题3:

int main()
{
 int a[4] = { 1, 2, 3, 4 };
 int *ptr1 = (int *)(&a + 1);
 int *ptr2 = (int *)((int)a + 1);
 printf( "%x,%x", ptr1[-1], *ptr2);
 return 0;
}

运行结果:

%x打印16进制数。

先来看ptr1[-1],它其实就相当于*(ptr-1),我们在第一题中讲过类似的,显然它打印出来的是4。

而(int)a将a强制类型转换成 int型,此时进行加一操作就是对a的值加一,假设a中的值是0x0012ff40,那(int)a+1的值就是0x0012ff41,而又将0x0012ff41作为地址给ptr2,此时就相当于跳过一个字节,然后向后访问4个字节,此时是小端存储,所以访问到的是00 00 00 02,还原以后就是02 00 00 00,打印时省略第一个0,结果就是2000000。

笔试题4:

#include <stdio.h>
int main()
{
 int a[3][2] = { (0, 1), (2, 3), (4, 5) };
 int *p;
 p = a[0];
 printf( "%d", p[0]);
 return 0;
}

打印结果:1

诶?为什么是1?结果不应该是0吗?

注意这个题有一个小小的坑,它在初始化二维数组时,大括号中用的是小括号,而不是{},所以()里面的是逗号表达式,逗号表达式的值是其中最后一个表达式的值,所以只将1,3,5存放了进去。

而p[0]等价于*(p+0) -->  *(a[0]+0)  -->  *(a[0]),a[0]是二维数组第一行数组的数组名,数组名又是数组首元素的地址,所以访问的是第一行第一个元素1。

笔试题5:

int main()
{
 int a[5][5];
 int(*p)[4];
 p = a;
 printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
 return 0;
}

运行结果:

首先我们可以知道的是a的类型是 int(*)[5],而p的类型是 int(*)[4],它们都是数组指针,a+1每次跳过5个整型,p+1每次跳过4个整型,p=a让它们的起始地址都是相同的,此时它们在内存中的关系如下图:

把p也看做一个二维数组会找到&p[4][2]的位置,而&p[4][2] - &a[4][2],两个指针相减得到的是他们之间的元素的个数,又因为随着下标的增长,地址是由低到高变化的,所相减得到的是-4,而-4用%p打印时,它在内存中的补码(11111111111111111111111111111110)作为地址是FFFFFFFC。

笔试题6:

int main()
{
 int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 int *ptr1 = (int *)(&aa + 1);
 int *ptr2 = (int *)(*(aa + 1));
 printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
 return 0;
}

打印结果:10 5

这个题比较简单,&aa取出整个二维数组的地址,&a+1跳过二维数组后的地址,赋给ptr1,所以*(ptr1-1)是数组最后一个元素10,而*(aa+1)就相当于aa[1],是第二行数组的数组名,即就是aa[1][0]的地址,所以*(ptr2-1)就是aa[1][0]的上一个元素aa[0][5]=5。

笔试题7:

#include <stdio.h>
int main()
{
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
}

打印结果:at

char*a[]是一个指针数组,其中存放的是三个char*型的指针,分别指向三个字符串首字符'w','a','a'的地址,而pa是二级指针变量,指向的是'w'的地址,所以pa++后,pa指向‘a’的地址,然后*pa通过%s打印出字符串“at”。

笔试题8:

int main()
{
 char *c[] = {"ENTER","NEW","POINT","FIRST"};
 char**cp[] = {c+3,c+2,c+1,c};
 char***cpp = cp;
 printf("%s\n", **++cpp);
 printf("%s\n", *--*++cpp+3);
 printf("%s\n", *cpp[-2]+3);
 printf("%s\n", cpp[-1][-1]+1);
 return 0;
}

打印结果:

首先,我们来看一下,c、cp、cpp在内存中的关系:

先来看**++cpp:

cpp先++,然后经过两次解引用,因为cpp中存放是cp,所以cp++指向cp+1,而cp+1解引用找到c+2,对c+2解引用找到字符'P'的地址,通过%s打印出POINT。(如下图)

再来看*--*++cpp+3:

明确这条代码中运算符的优先级由高到低依次是:++*+,所以+3一定是最后进行的,先进行++cpp,注意经过上条代码后,cpp中存放的是cp+1,所以再进行++cpp,指向的是cp+2,对cp+2解引用得到c+1,对--(c+1)得到c,对c解引用得到字符'E'的地址,+3得到字符'E'的地址,通过%s往后打印出ER。

接着来看*cpp[-2]+3:

它可以写成 **(cpp-2)+3, 经过前两条代码,此时cpp中存放的内容又变成了cp+2,所以cpp-2指向的就是cp+2-2=cp,对cp解引用得到c+3,对c+3解引用得到字符'F'得地址,+3得到字符'S'的地址,通过%s往后打印出ST。

最后来看一下cpp[-1][-1]+1:

它可以写成*(*(cpp-1)-1)+1,此时cpp中的内容还是cp+2,所以cpp-1得到cp+1,对cp+1解引用得到c+2,对c+2-1得到c+1,对c+1解引用得到字符'N'的地址,+1得到字符'E'的地址,通过%s往后打印出EW。

以上就是关于一些关于指针的笔试题及详细解析,

那么今天就学到这里啦,未完待续。。。

目录
相关文章
|
1月前
|
存储 C语言
【C语言篇】深入理解指针3(附转移表源码)
【C语言篇】深入理解指针3(附转移表源码)
37 1
|
29天前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
48 0
|
27天前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
17 2
|
28天前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
28天前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
1月前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
1月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
1月前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
1月前
|
C语言
C语言指针(3)
C语言指针(3)
14 1
|
1月前
|
C语言
C语言指针(2)
C语言指针(2)
15 1
下一篇
无影云桌面