(汇编分析)字符指针数组与二维字符数组

cc str str1 的数组赋值及其汇编代码如下

    int cc[2][2] = {{1,2},{3,4}};
00D63598  mov         dword ptr [ebp-18h],1 
00D6359F  mov         dword ptr [ebp-14h],2 
00D635A6  mov         dword ptr [ebp-10h],3 
00D635AD  mov         dword ptr [ebp-0Ch],4 
    char *str[] = {"abg","cd"};
00D635B4  mov         dword ptr [ebp-28h],offset string "abg" (0D65808h) 
00D635BB  mov         dword ptr [ebp-24h],offset string "cd" (0D657ACh) 
    char str1[2][10] = {"abg","cd"};
00D635C2  mov         eax,dword ptr [string "abg" (0D65808h)] 
00D635C7  mov         dword ptr [ebp-44h],eax 
00D635CA  xor         eax,eax 
00D635CC  mov         dword ptr [ebp-40h],eax 
00D635CF  mov         word ptr [ebp-3Ch],ax 
00D635D3  mov         ax,word ptr [string "cd" (0D657ACh)] 
00D635D9  mov         word ptr [ebp-3Ah],ax 
00D635DD  mov         cl,byte ptr ds:[0D657AEh] 
00D635E3  mov         byte ptr [ebp-38h],cl 
00D635E6  xor         eax,eax 
00D635E8  mov         dword ptr [ebp-37h],eax 
00D635EB  mov         word ptr [ebp-33h],ax 
00D635EF  mov         byte ptr [ebp-31h],al 

做实验

1.能不能将二维数组名传递给二级指针?

1.把int类型二维数组cc传给

void change(int ** p)
{
    printf("%d\n",p);
    printf("%d\n",*p);
    printf("%d\n",**p);

}
change(cc); //这样调用: warning C4024: “change”: 形参和实参 1 的类型不同 为什么会报错?
//原因
//p是一个二级指针,它首先是一个指针,指向一个int*;
//cc是二维数组名,它首先是一个指针,指向一个含有2个元素的int数组;

//下方强转换类型时就可以使用了
change((int **)cc)

//当我们进行强转后看一下 p, *p ,**p,表示的值
//result:
p 1366256
*p 1
**p 出错
原因:
1)首先看一下p的值,p指向cc[0][0],即p的值为cc[0][0]的地址;

2)再看一下*p的值,p所指向的类型是int*,占4字节,根据前面所讲的解引用操作符的过程:从p指向的地址开始,取连续4个字节的内容。得到的正式cc[0][0]的值,即0。

3)再看一下**p的值,诶,报错了?当然报错了,因为你访问了地址为0的空间,而这个空间你是没有权限访问的。

但是有个问题真的没法访问吗 ?首先p 可以访问 *p也可以访问 只有**p不可以访问 那么只要能访问就可以得到数组里面的值
#include<stdio.h>

void change(int **p)
{
    int i = 0;
    for(i=0;i<4;i++)
    {   
    printf("%d\n",*(p+i));
    }
    *p = 5;
}
int  main()
{
    int cc[2][2] = {{1,2},{3,4}};

    change((int**)cc);

}
上述可以看到 是可以被访问和改变的,但是无法采用    printf("%d",p[0][0]);这种方式来访问,
这就引出来了一个问题,下标访问与指针间访问的关系 ,如果满足上方所说的p[0][0],这种关系那么肯定存在着二级指针
可以被有效访问的情况可是经过我们的试验发现,是不存在的!

//接下来我们从汇编的角度进行分析
00D63598  mov         dword ptr [ebp-18h],1 
00D6359F  mov         dword ptr [ebp-14h],2 
00D635A6  mov         dword ptr [ebp-10h],3 
00D635AD  mov         dword ptr [ebp-0Ch],4 
p 为ebp-18地址的值(因为整数在内存中占用四个字节实际上应该为14h-h18)
*p[ebp-18]堆栈里的值进行输出,为1
**p 为[1]的值进行寻址当然就报错了

经过以上的试验 ,int类型二维数组并不能那么做!
2.接下来我们用char 型二维数组str1传给change

void change(char ** p)
{
    printf("%d\n",p);
    printf("%d\n",*p);
    printf("%d\n",**p);

}
//change(str1);//和上面的不同 ,没报错
//change((char**)str1) //和change(str1)输出的结果相同
//同时运行上方的两句,在不运行**p的情况下是相同的,为什么?
1768488
1684234849
1768488
1684234849
//原因:
00D635C2  mov         eax,dword ptr [string "abg" (0D65808h)] 
00D635C7  mov         dword ptr [ebp-44h],eax 
00D635CA  xor         eax,eax 
00D635CC  mov         dword ptr [ebp-40h],eax 
00D635CF  mov         word ptr [ebp-3Ch],ax 
00D635D3  mov         ax,word ptr [string "cd" (0D657ACh)] 
00D635D9  mov         word ptr [ebp-3Ah],ax 
00D635DD  mov         cl,byte ptr ds:[0D657AEh] 
00D635E3  mov         byte ptr [ebp-38h],cl 
00D635E6  xor         eax,eax 
00D635E8  mov         dword ptr [ebp-37h],eax 
00D635EB  mov         word ptr [ebp-33h],ax 
00D635EF  mov         byte ptr [ebp-31h],al 
因为在压栈只是压栈为字符串的准确数值而不是地址,地址和地址里的值是有很大区别的,这一点很容易混淆!
例如
00D635C2  mov         eax,dword ptr [string "abg" (0D65808h)] 
00D635C7  mov         dword ptr [ebp-44h],eax 
意思就是把0D65808h入堆栈之中
,而准确数值用十六进制表示,那么首地址的指针为
int*型的指针,而在c语言中还指针都为四字节 那么传进去也不会报错了,但是str1还是指向字符数组的指针 !


然后继续回答我们的问题当做二级指针传进去后我们发现并不能打印出,char型二维数组的值 ,所以char型的也不可以

综上而得:其实声明为二级指针是可以进行取值的

2.二维数组的赋值与访问

``
//对于字符型数组的访问与修改
//1.常规访问


#include<stdio.h>

void change(char(*p)[3])
{
    p[0][0]='C';
    printf("%c\n",p[0][0]);


}
void change1(char p[3][3])
{
    p[0][0]='C';
    printf("%c\n",p[0][0]);


}
int main()
{
    char str1[3][3] = {"ab","\0","da"};

    change(str1);
    printf("%\n",str1[0]);

    return 0;


}


2.非常规访问(无法访问到整个值!)

#include<stdio.h>

void change(char *a)
{
    int i=0;
    for(i=0;i<10;i++)
    {
    
        printf("%c\n",*(a+i));
    }
}


int  main()
{
    char str1[3][3] = {"ab","\0","da"};
    char *a = &str1[0];
    change(a);
    //printf("%s\n",str1[0]);
    return 0;

}


#include<stdio.h>

void change(char ** p)
{
    //printf("%d\n",p);
    printf("%c\n",*p);
    //printf("%d\n",**p);

}
int  main()
{
    char str1[2][10] = {"abg","cd"};
    change((char **)str1);
    //printf("%s\n",str1[0]);
    return 0;

}
因为在内存中所有的数组地址都是按照线性排列 只要获取到了开头的一个地址通过地址加减的情况可以访问到所有的地址,但是都无法访问到整个的值得
3.二维数组和指针数组

从前面我们已经介绍二维数组了

那么指针数组的实现下

#include<stdio.h>

void change(char ** p)
{

    printf("%s\n",*p);

}
int  main()
{
    char * str1[] = {"abg","cd"};
    change(str1);
    //printf("%s\n",str1[0]);
    return 0;

}

//结果abg,是直接可以取到的 

因为什么呢

char *str[] = {"abg","cd"};
00D635B4  mov         dword ptr [ebp-28h],offset string "abg" (0D65808h) 
00D635BB  mov         dword ptr [ebp-24h],offset string "cd" (0D657ACh) 

指针数组首地址的里面存放的值 相当于*p 是一个 字符串偏移的地址

而在

    char str1[2][10] = {"abg","cd"};
00D635C2  mov         eax,dword ptr [string "abg" (0D65808h)] 
00D635C7  mov         dword ptr [ebp-44h],eax 
00D635CA  xor         eax,eax 
00D635CC  mov         dword ptr [ebp-40h],eax 
00D635CF  mov         word ptr [ebp-3Ch],ax 
00D635D3  mov         ax,word ptr [string "cd" (0D657ACh)] 
00D635D9  mov         word ptr [ebp-3Ah],ax 
00D635DD  mov         cl,byte ptr ds:[0D657AEh] 
00D635E3  mov         byte ptr [ebp-38h],cl 
00D635E6  xor         eax,eax 
00D635E8  mov         dword ptr [ebp-37h],eax 
00D635EB  mov         word ptr [ebp-33h],ax 
00D635EF  mov         byte ptr [ebp-31h],al 

相当于首地址单元模块存放的值为实际的值 ,所以多维指针的二级指针无法找到,这也是为什么平时不要对二维数组使用二级指针的问题!
QQ图片20191107232233.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270