the difference between pointer and array (and variable)

2024-01-21 19:32

本文主要是介绍the difference between pointer and array (and variable),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

/********************************test,c***********************
song 
8.13
*************************************************************/
#include<stdio.h>  
int i=6;
int cc[9]={1,2,3,4,5,6,7,8,9};
int * const pa=cc;//注意const的位置:不是const int * pa,
int *  ppa=cc;
int bb[2][3]={{0x50,0x51,0x52},{0x53,0x54,0x55}};int main()  
{i=3;
i=3;
*(cc+1)=6;
*(pa+1)=8;
*(ppa+1)=9;
*(*(bb+1)+1)=0x99;
i=2;
i=2;printf("%x\n",i);
printf("%x\n",*(cc+1));
printf("%x\n",*(pa+1));
printf("%x\n",*(ppa+1));
printf("%x\n",*(*(bb+1)+1));printf("%x\n",cc);
printf("%x\n",pa);
printf("%x\n",ppa);
printf("%x\n",bb);printf("%x\n",&i);
printf("%x\n",&cc);
printf("%x\n",&pa);
printf("%x\n",&ppa);
printf("%x\n",&bb);
}
[root@localhost mmap]# ./test
2
9
9
9
99
8049800
8049800
8049800
8049828
80497e0
8049800
8048634
8049824
8049828
//print sections
[root@localhost mmap]# readelf -S test[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al[15] .rodata           PROGBITS        08048628 000628 000014 00   A  0   0  4[24] .data             PROGBITS        080497c0 0007c0 000080 00  WA  0   0 32
//print symblols
[root@localhost mmap]# readelf -s testNum:    Value  Size Type    Bind   Vis      Ndx Name46: 08048634     4 OBJECT  GLOBAL DEFAULT   15 pa53: 08049800    36 OBJECT  GLOBAL DEFAULT   24 cc57: 080497e0     4 OBJECT  GLOBAL DEFAULT   24 i62: 08049828    24 OBJECT  GLOBAL DEFAULT   24 bb65: 08049824     4 OBJECT  GLOBAL DEFAULT   24 ppa
[root@localhost mmap]# objdump -s testContents of section .rodata:8048628 03000000 01000200 00000000 00980408  ................
/*
the address of pa is starting from 8048634 ,length 4 bytes,it's content 
is "00980408" displaying as little endian
actually it is 08049800---the address of cc
*/
Contents of section .data:80497c0 00000000 00000000 00000000 00000000  ................80497d0 00000000 00000000 00000000 00000000  ................80497e0 06000000 00000000 00000000 00000000  ................80497f0 00000000 00000000 00000000 00000000  ................8049800 01000000 02000000 03000000 04000000  ................8049810 05000000 06000000 07000000 08000000  ................8049820 09000000 00980408 50000000 51000000  ........P...Q...8049830 52000000 53000000 54000000 55000000  R...S...T...U...
/*
the address of cc is starting from 08049800 ,4*9=36 bytes length ,we can see it's 
content is 1 2 3 4 5 6 7 8 9 from data section
the address of bb is starting from 08049828 , 4*2*3=24 bytes length
cotent is 50 51 52 53 54 55
the address of i is starting from 080497e0 , 4 bytes length,cotent is 6
the address of ppa is starting from 08049824 , the length and cotent are the same as pa
located in rodata section
*/

可用下图表示变量,指针,数组的内存分分配


[root@localhost mmap]# objdump -S test
080483c4 <main>:80483c4:	8d 4c 24 04          	lea    0x4(%esp),%ecx80483c8:	83 e4 f0             	and    $0xfffffff0,%esp80483cb:	ff 71 fc             	pushl  -0x4(%ecx)80483ce:	55                   	push   %ebp80483cf:	89 e5                	mov    %esp,%ebp80483d1:	51                   	push   %ecx80483d2:	83 ec 14             	sub    $0x14,%esp80483d5:	c7 05 e0 97 04 08 03 	movl   $0x3,0x80497e0//i=3;80483dc:	00 00 00 80483df:	c7 05 e0 97 04 08 03 	movl   $0x3,0x80497e0//i=3;80483e6:	00 00 00 
/*$表示一个立即数,%表示一个寄存器,( )表示寄存器间接寻址
编译器将i用其地址0x80497e0替换掉
翻译为将立即数3移到内存单元0x80497e0*/80483e9:	b8 04 98 04 08       	mov    $0x8049804,%eax//*(cc+1)=6;80483ee:	c7 00 06 00 00 00    	movl   $0x6,(%eax)
/*
编译器将cc+1用cc+1所表示的地址值替换掉
cc+1-->8049800+4=8049804
编译器将*(cc+1)翻译为将计算出来的地址塞进累加器eax,
利用寄存器间接寻址将立即数6塞进内存单元8049804
*/80483f4:	a1 34 86 04 08       	mov    0x8048634,%eax//*(pa+1)=8;80483f9:	83 c0 04             	add    $0x4,%eax80483fc:	c7 00 08 00 00 00    	movl   $0x8,(%eax)
/*
编译器将pa用pa之地址替换下来
编译器将*(pa+1)翻译为将pa地址8048634塞进eax
执行+1操作,即eax=8048634+4=8048638
将立即数塞进8048638内存单元
*/8048402:	a1 24 98 04 08       	mov    0x8049824,%eax//*(ppa+1)=9;8048407:	83 c0 04             	add    $0x4,%eax804840a:	c7 00 09 00 00 00    	movl   $0x9,(%eax)
/*
同*(pa+1)=8;可以看出,指针常量和指针都被编译器翻译成一样的代码,
数组名cc+1,cc[1]等都是编译器编译时执行的的运算
pa+1是程序运行时执行的运算
所以,数组名只是一个c语言的规定,用于编译器计算数组元素的地址值,
c语言在数组范畴规定了这么多的东西,要求我们按照他说的规范去写,然后他在编译的时候,直接套用
规范计算出实际地址,而不是在程序运行的时候去计算指针常量和指针都是有一个32b的内存单元来装其值得
数组名没有
数组名在内存中更像是普通变量(的集合)
但是在c语言中,大部分场合,要将数组名"假想"作一个指针去用,
这是c语言规范,因为 编译时,是将数组名当做指针对待
比如将cc[1]先在内部译成*(cc+1)
这也就解释了指针也可以写成数组的形式,因为即使你写成了数组的形式(不管实际是数组还是指针)
,编译器还是会将其换成指针
一下来自 thq c程序设计
int *p;
int a[10];
p=&a[0](或p=a);
则
p+i,a+i都是a[i]的地址.a[i]也可写作p[i]
*(p+i),*(a+i)都是p+i或a+i指向的数组元素即a[i]的值
比如p+2,代表a[2]的地址,或说p[2]的地址
*/8048410:	b8 28 98 04 08       	mov    $0x8049828,%eax//*(*(bb+1)+1)=0x99;8048415:	83 c0 10             	add    $0x10,%eax8048418:	c7 00 99 00 00 00    	movl   $0x99,(%eax)
/*
8049828+12+4
*/
804841e:    c7 05 e0 97 04 08 02     movl   $0x2,0x80497e0//i=2;8048425:    00 00 00 8048428:    c7 05 e0 97 04 08 02     movl   $0x2,0x80497e0//i=2;804842f:    00 00 00 8048432:    a1 e0 97 04 08           mov    0x80497e0,%eax8048437:    89 44 24 04              mov    %eax,0x4(%esp)804843b:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)8048442:    e8 ad fe ff ff           call   80482f4 <printf@plt>8048447:    b8 04 98 04 08           mov    $0x8049804,%eax804844c:    8b 00                    mov    (%eax),%eax804844e:    89 44 24 04              mov    %eax,0x4(%esp)8048452:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)8048459:    e8 96 fe ff ff           call   80482f4 <printf@plt>804845e:    a1 34 86 04 08           mov    0x8048634,%eax8048463:    83 c0 04                 add    $0x4,%eax8048466:    8b 00                    mov    (%eax),%eax8048468:    89 44 24 04              mov    %eax,0x4(%esp)804846c:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)8048473:    e8 7c fe ff ff           call   80482f4 <printf@plt>8048478:    a1 24 98 04 08           mov    0x8049824,%eax804847d:    83 c0 04                 add    $0x4,%eax8048480:    8b 00                    mov    (%eax),%eax8048482:    89 44 24 04              mov    %eax,0x4(%esp)8048486:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)804848d:    e8 62 fe ff ff           call   80482f4 <printf@plt>8048492:    b8 28 98 04 08           mov    $0x8049828,%eax8048497:    83 c0 10                 add    $0x10,%eax804849a:    8b 00                    mov    (%eax),%eax804849c:    89 44 24 04              mov    %eax,0x4(%esp)80484a0:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)80484a7:    e8 48 fe ff ff           call   80482f4 <printf@plt>80484ac:    c7 44 24 04 00 98 04     movl   $0x8049800,0x4(%esp)80484b3:    08 80484b4:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)80484bb:    e8 34 fe ff ff           call   80482f4 <printf@plt>80484c0:    a1 34 86 04 08           mov    0x8048634,%eax80484c5:    89 44 24 04              mov    %eax,0x4(%esp)80484c9:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)80484d0:    e8 1f fe ff ff           call   80482f4 <printf@plt>80484d5:    a1 24 98 04 08           mov    0x8049824,%eax80484da:    89 44 24 04              mov    %eax,0x4(%esp)80484de:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)80484e5:    e8 0a fe ff ff           call   80482f4 <printf@plt>80484ea:    c7 44 24 04 28 98 04     movl   $0x8049828,0x4(%esp)80484f1:    08 80484f2:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)80484f9:    e8 f6 fd ff ff           call   80482f4 <printf@plt>80484fe:    c7 44 24 04 e0 97 04     movl   $0x80497e0,0x4(%esp)8048505:    08 8048506:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)804850d:    e8 e2 fd ff ff           call   80482f4 <printf@plt>8048512:    c7 44 24 04 00 98 04     movl   $0x8049800,0x4(%esp)8048519:    08 804851a:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)8048521:    e8 ce fd ff ff           call   80482f4 <printf@plt>8048526:    c7 44 24 04 34 86 04     movl   $0x8048634,0x4(%esp)804852d:    08 804852e:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)8048535:    e8 ba fd ff ff           call   80482f4 <printf@plt>804853a:    c7 44 24 04 24 98 04     movl   $0x8049824,0x4(%esp)8048541:    08 8048542:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)8048549:    e8 a6 fd ff ff           call   80482f4 <printf@plt>804854e:    c7 44 24 04 28 98 04     movl   $0x8049828,0x4(%esp)8048555:    08 8048556:    c7 04 24 38 86 04 08     movl   $0x8048638,(%esp)804855d:    e8 92 fd ff ff           call   80482f4 <printf@plt>8048562:    83 c4 14                 add    $0x14,%esp8048565:    59                       pop    %ecx8048566:    5d                       pop    %ebp8048567:    8d 61 fc                 lea    -0x4(%ecx),%esp804856a:    c3                       ret    804856b:    90                       nop    804856c:    90                       nop    804856d:    90                       nop    804856e:    90                       nop    804856f:    90                       nop    



这篇关于the difference between pointer and array (and variable)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/630593

相关文章

array_walk()使用

bool  array_walk (  array &$array ,  callable $callback [,  mixed $userdata = NULL ] ) 将用户自定义函数 funcname 应用到 array 数组中的每个单元。 array_walk() 不会受到 array 内部数组指针的影响。array_walk() 会遍历整个数组而不管指针的位置。 array

【C++11 之新增容器 array、foward_list、tuple、unordered_(multi)map/set】应知应会

C++11 标准中新增了多个容器,这些容器为 C++ 程序员提供了更多的选择,以满足不同的编程需求。以下是对这些新容器的介绍和使用案例: std::array 介绍: std::array 是一个固定大小的数组容器,它在栈上分配内存,并提供了类似于标准库容器的接口。它提供了更好的类型安全性和范围检查,同时保持了与原生数组相似的性能。std::array 的大小必须在编译时确定,并且不能更改。

如何解决matplotlib运行出现的Invalid DISPLAY variable

最近在服务器上运行matplotlib相关的脚本时遇到了"Invalid DISPLAY variable"报错,从报错中就可以知道这是因为没有显示设备导致的报错。 解决方案: 方案一: ~/.config/matplotlib/matplotlibr,在里面添加backend : Agg 这个方案不一定有用,如果失效考虑下面两种 方案二: 更换后端 可以先设置后端,然后导入pyp

Python中的range()与array()函数

我们在Python中存在一个非常好用的range()与array()函数,下面作用法简要介绍。 一、range()函数   >>> range(1,10)   ——>不包括10[1, 2, 3, 4, 5, 6, 7, 8, 9]>>>range(1,10,2)  ——>1到10,间隔为2(不包括10)[1, 3, 5, 7, 9]>>>range(10)    ——>0到10,不

array_key_exists() expects parameter 2 to be array, null given

公众号获取微信服务器IP地址 错误代码如下 public function getwxIP(){//获取微信服务器IP地址$accessToken = $this->getwxoaiAccessToken();$userToken = new UserToken();$result = $userToken->curl_get("https: //api.weixin.qq.com/cgi-

OSS报错The difference between the request time and the current time is too large

目录 一、问题描述二、问题原因三、解决方法 一、问题描述 文件上传阿里云 OSS 报错: The difference between the request time and the current time is too large 二、问题原因 请求发起的时间超过 OSS 服务器当前时间 15 分钟,OSS 判定该请求无效,返回报错。 三、解决方法 OSS

C++之std::condition_variable::wait_for

std::condition_variable::wait_for 是 C++11 引入的条件变量的一部分,用于在一定时间内等待通知。它是 std::condition_variable 类的成员函数之一,可以使线程在等待某条件变为真时,最多等待指定的时间段。 使用方法 在 std::condition_variable 中,wait_for 的主要形式如下: cpp template

C#中的数组Array和List集合区别

在C#中,数组(Array)和List集合(List<T>)是两种不同的数据结构,它们有一些区别,主要包括以下几点: 固定长度 vs 动态长度: 数组是固定长度的数据结构,一旦创建后,其长度无法改变。 List集合是动态长度的数据结构,可以根据需要动态增加或减少元素。 类型限制: 数组可以存储任意类型的元素,包括值类型和引用类型。 List集合是泛型集合,可以指定存储的元素类型,例如 Li

442. Find All Duplicates in an Array 找数组中重复的数

https://leetcode-cn.com/problems/find-all-duplicates-in-an-array/description/ 题意:找出数组中所有重复的元素 思路1:先将数组排序,然后判断是否重复,即若nums[i] != nums[i+1],即说明nums[i]非重复元素,可以删去. 重点在于指针(迭代器)的操作,由于vector的erase(删除)操作需要通

[Codeforces 451B] Sort the Array (实现)

Codeforces - 451B 给定一个序列,其中每个数都不相同 问是否能在翻转其中一段后,整个序列变得单调递增 实现题 首先设一个 B B数组为 AA数组排序后的结果 由于只能翻转一个区间,那么我假装 A是满足要求的 找到最小的 A[l]≠B[l] A[l] \ne B[l],最大的 A[r]≠B[r] A[r] \ne B[r], 翻转的区间将会是 [l,r