恩光汽车新闻网

您现在的位置是: 首页 > 汽车新闻

文章内容

c语言指针越界_c语言指针越界怎么解决

tamoadmin 2024-08-16
1.c语言中 数组的问题?2.c语言为什么说指针是灵魂?能简单举个例子吗?谢谢3.关于C语言中的指针问题?4.求大牛解决c语言指针的强制转化问题!!!!!加上(

1.c语言中 数组的问题?

2.c语言为什么说指针是灵魂?能简单举个例子吗?谢谢

3.关于C语言中的指针问题?

4.求大牛解决c语言指针的强制转化问题!!!!!加上(short *)有什么用?

5.c语言关于指针的求解

6.C语言指针指向二位数组的疑问?

7.C语言中的指针和内存泄漏

c语言指针越界_c语言指针越界怎么解决

int a[2][3]; 定义了一个二维函数,每一维数组有三个元素。

int (*pt)[3]; 定义了一个数组指针,也就是定义了一个指向有三个元素的指针,即该指针,每次自加1,地址跳过三个int

pt=a; 就是让pt指向a[0],注意a[0]是一个数组地址,里面有三个元素

对于A选项,pt[0][0]是正确的,pt[0][0]等价于a[0][0]

对于B选项,不正确,因为pt+1就是a[1], *(pt+1)[2]相当于a[3][0]不对。

因为运算符优先级,[]大于*,因此*(pt+1)[2]就是*pt[1+2] 也就是*a[1+2]。而*a[3]就等价于a[3][0]。越界了

改成(*(pt+1))[2]就对了,相当于a[1][2]

对于C选项,正确,*(pt[1]+2) 相当于a[1][2]

对于D选项,正确,*(a[0]+2)相当于a[0][2]

c语言中 数组的问题?

1、*(p[2])其实是一个没初始化的元素,你的int (*p)[3]定义的p是一个指向数组的指针,这个数组中有三个int元素,所以*(p[0])就是第一个数组的第一个元素(也就是data[0][0]),*(p[1])是第二个数组的第一个元素(也就是data[1][0]),实际上你要访问data[i][j],可以通过printf("%d\n",*(*(p+i)+j));

2、C里对指针越界没有明确的检查,发生越界时程序可以正常也可能崩溃。

3、前者定义的是一个指针,后者定义的是一个数组,具体请参照网页链接

c语言为什么说指针是灵魂?能简单举个例子吗?谢谢

这个问题和c语言的编译器有关。

1.那么c是怎么记录arr数组的长度是多少呢?

这个arr的长度是被算出来的,int说明一个数据的长度为32bit,也就是4个字节。 [3]表示有3个这样的数据类型。所以是12个字节。 编辑器会算出,并分配空间。

2.就是arr的长度保存在哪里?即c怎么知道从arr[0]后面有几个连续的地址?

长度是不被bao 保存的。只是在分配的时候会算出来,并使用。 一旦分配完空间,实际上被纪录的只有一个指针的地址。 所以在用指针地址访问空间的时候要特别注意。地址不要出错,或者越界。

关于C语言中的指针问题?

我们知道执行指针是危险的,执行指针很容易就会现在指针越界问题,如果是赋值操作将会对系统造成很大的危险,相信每一个程序员都会用指针取数时取过不属于自已定义的内存单元,C#里都摈弃了指针……可想而知指针的意义是不大的,完成可以用数组来代替。在C中看来,指针是完全可以替代数组的,但数组有什么它自已的优点呢?1.当你想定义一组数据变量时,十个变量?或许你还可以每个变量给它取个名字,可如果是100个,1000个呢?1000个的指针变量,每个指针你就给它取名都取到头痛,别说编写程序了。或许你会反驳,用指针动态申请也可以,很明显如果你用指针来替代数组,这时指针就不能移动了,因为一移动,它就乱了,你就不知道当前指针是指向哪里下一个内存单元又是哪里了,如果不能移动,指针也就失去了它的意义了……还有如果申请的不是连续的内存空间,比哪1000个连续的1000个单元的内存空间块呢?你是不是还得定义1000个指针变量来动态申请内存,而用数组你就可以避免,你只要定义1000个数组指针,再用循环实现动态申请就可以。2.数组定义的是一组连续的内存空间,可以说每个单元都有自已的变量名(数组名+下标)……这样如果执行越界操作时,程序将会报错……3.还有就是用数组申请一组连续的内存空间明显要比用指针动态申请空间要简单得多……4.再者数组是用到很多的,如果你全部都用针指来代替,我们知道执行指针是危险的,多一个针指操作就多一分危险,你能保证,程序编写一次就能正常运行,你这么多的针指就不会指向一些重要的系统或用户数组去操作?*只要你编写的程序够多,不难发现,数组远比指针要简单得多……

求大牛解决c语言指针的强制转化问题!!!!!加上(short *)有什么用?

同学你是没理解指针是什么意思。

Root = NULL的意思是将Root指向一处空的位置,这时候Root里面的一切都是空的(没有开辟内存空间),当运行到Root->data.value的时候,程序尝试读取Root里面的data元素,这时候就会出现读取内存越界,因为Root指向的地方是空(没有分配内存)。

c语言关于指针的求解

指针的强制转换 并不影响最终的结果

更多的是给编译器用的。

在C里面对指针不同类型相互赋值做的要求级别并不高

当源类型和目标类型不匹配时只是报一个warning, 而C++里面就是错误了。

比如你这个 正确做法应该是

p=(char *)&a;

至于为什么要加强制转换, 其最根本的原因是

不同类型的指针,进行相互赋值的时候是很容易出现越界的。比如char *p, 这个指针可能只指向一个字节的单元,(char c; p=&c;这样), 如果赋值给int*q=p; 然后按照*q去赋值取值,就是绝对的越界操作。

对于编程中,如果不小心写错了,那么就会引起不可预知后果,甚至可能是你运行测试几十次都正常,但真正出成品了,到客户手里莫名其妙的出错,查起来超难。

所以要求加强制转换,就是为了避免这样的不小心。 人性化一点的说,就是告诉编译器,我知道我在不同类型之间赋值,我已经知道了这样做的后果,也已经确定了可以承担这个后果,你不要管我了。 于是编译器就不管了,后果嘛,自负。

C语言指针指向二位数组的疑问?

int x[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, *p1;

(A) x[3]// x[3]=3 数组从0开始,3其实是第四个

(B) p1 = x + 3, *p1++ //先执行p1=x+3,也就是指向x[3],因为p1定义成指针。*p1++ 这时候先执行再加,这表达式仍然是3

(C) p1 = x + 2, *(p1++) //p=x+2 ,x数组的地址加2,也就是指向x[2],x=2,这时候p++同时也是先执行后加,所以取出x[2]的值,所以等于2

(D) p1 = x + 2, *++p1//同样,p1指向x[2],但++是先加再执行*取值,所以++p指向x[3],取出来的值就是3

答案是 C

C语言中的指针和内存泄漏

一条一条来

(1)*(p[2])为何也是-2147456552?它怎么会指向第一行(第一列)?

*(p[2])就是 data[2][0]; 对于data数组来说,它已经越界了,它读取的是data数组最后一个元素的下一个地址内的数据,在这个例子里,这个地址恰好就是p的空间,而p保存的就是data的地址,所以一样输出data的地址,注意这是恰好,给p分配的内存恰好就紧挨着data,不同的编译器,不同环境下,不一定是这样

(2)根据“int (*p)[3] ”,定义的(*p)长度为3,(*p)[3],(*p)[4],(*p)[5]应当都是非法的吧?怎么会有值?还是依次的

data的空间是连续的?(*p)[3] 就是data[0][3] ,也就是 data[1][0],对于data[0]来说,它越界了,对于整个data来说,没越界

(3)(*p)[n]与*(p[n])到底什么区别?值不同应怎么解释?

这样解读:(*p)[n] , 有括号,所以p与*结合,那么p就是个指针,然后发现有[n], 那么就说明这个指针指向一个一维数组,所以p是个指针,它指向一个长度是n的一维数组

*(p[n]);? 这也就是*p[n] ; p先和[]结合,说明p是个数组,然后再与*结合,说明这个数组的元素是* , 也就是说,p是个数组,它有n个元素,每个元素都是指针

对于任何使用 C 语言的人,如果问他们 C 语言的烦恼是什么,其中许多人可能会回答说是指针和内存泄漏。这些的确是消耗了开发人员大多数调试时间的事项。指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的大工具。

本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密。本文内容包括:

导致内存破坏的指针操作类型

在使用动态内存分配时必须考虑的检查点

导致内存泄漏的场景

如果您预先知道什么地方可能出错,那么您就能够小心避免陷阱,并消除大多数与指针和内存相关的问题。

什么地方可能出错?

有几种问题场景可能会出现,从而可能在完成生成后导致问题。在处理指针时,您可以使用本文中的信息来避免许多问题。

未初始化的内存

在本例中,p 已被分配了 10 个字节。这 10 个字节可能包含垃圾数据,如图 1 所示。

char *p = malloc ( 10 );

图 1. 垃圾数据

如果在对这个 p 赋值前,某个代码段尝试访问它,则可能会获得垃圾值,您的程序可能具有不可预测的行为。p 可能具有您的程序从未曾预料到的值。

良好的实践是始终结合使用 memset 和 malloc,或者使用 calloc。

char *p = malloc (10);

memset(p,’\0’,10);

现在,即使同一个代码段尝试在对 p 赋值前访问它,该代码段也能正确处理 Null 值(在理想情况下应具有的值),然后将具有正确的行为。

内存覆盖

由于 p 已被分配了 10 个字节,如果某个代码片段尝试向 p 写入一个 11 字节的值,则该操作将在不告诉您的情况下自动从其他某个位置“吃掉”一个字节。让我们设指针 q 表示该内存。

图 2. 原始 q 内容

图 3. 覆盖后的 q 内容

结果,指针 q 将具有从未预料到的内容。即使您的模块编码得足够好,也可能由于某个共存模块执行某些内存操作而具有不正确的行为。下面的示例代码片段也可以说明这种场景。

char *name = (char *) malloc(11);

// Assign some value to name

memcpy ( p,name,11); // Problem begins here

在本例中,memcpy 操作尝试将 11 个字节写到 p,而后者仅被分配了 10 个字节。

作为良好的实践,每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。一般情况下,memcpy 函数将是用于此目的的检查点。

内存读取越界

内存读取越界 (overread) 是指所读取的字节数多于它们应有的字节数。这个问题并不太严重,在此就不再详述了。下面的代码提供了一个示例。

char *ptr = (char *)malloc(10);

char name[20] ;

memcpy ( name,ptr,20); // Problem begins here

在本例中,memcpy 操作尝试从 ptr 读取 20 个字节,但是后者仅被分配了 10 个字节。这还会导致不希望的输出。