c语言的汇编表示 数组,指针和字符串
1.
void func(int a[])
{
}
int main ()
{
int a[10];
func(a[1]); //报错 原因:a[1]被当作是一个int类型 ,并不奇怪
return 0;
}
int main ()
{
int a[10];
func(a[1]); //这样就没有问题
return 0;
}
void func(int a)
{
}
2.
void func(int a[11])
{
//居然可以在形参中定义带有大小的数组,吃惊
}
3.
void func1(int a[])
{
}
void func2(int* a)
{
}
int main ()
{
int a[10];
//这两种传参方式在汇编角度没有任何区别,都是传入数组首地址,
也就是说可以fun1和fun2内更改a[10]的值
func1(a);
func2(a);
return 0;
}
汇编代码
func1(a);
00BB1963 lea eax,[ebp-2Ch]
00BB1966 push eax
00BB1967 call 00BB12C6
00BB196C add esp,4
func2(a);
00BB196F lea eax,[ebp-2Ch]
00BB1972 push eax
00BB1973 call 00BB12C1
00BB1978 add esp,4
所以我可以这样
void func1(int a[])
{
int i=2;
*(a+i)=1;
a[i]=1;
}
void func2(int* b)
{
int i=2;
*(b+i)=1;
b[i]=1;
}
4.
int main ()
{
const char* a="abcde";
//为什么可以这么赋值?因为“abcde”实际上就是这个const char*这个类型
//双引号表示编译器会在常量区存储‘a’'b''c''d''e''\0'
//然后用你写的"abcde"来表示常量区的那个字符串的首地址
}
同样的你还可以这样
void func(const char* a)
{
}
int main ()
{
func("wa");
}
5.
int main ()
{
char* a = (char*)"abcde";
a[1] = 2;
//我可以这样吗? 不能,因为常量区的代码是不可改的
//是真的不能改吗?其实我们可以调用windows提供的api来更改内存权限
//virtualprotect(),修改字符串之后记得把权限改回来
}
为什么用下面的方式不用更改内存权限
int main ()
{
char a[]="dwad";
a[1] = 2;
}
查看反汇编代码
char a[]="dwad";
002C15A3 mov eax,dword ptr ds:[002C5C34h]
002C15A8 mov dword ptr [ebp-0Ch],eax
002C15AB mov cl,byte ptr ds:[002C5C38h]
002C15B1 mov byte ptr [ebp-8],cl
a[1] = 2;
002C15B4 mov eax,1
002C15B9 shl eax,0
002C15BC mov byte ptr [ebp+eax-0Ch],2
寄存器把常量区的字符串复制到了数组中
a[i]=2;修改的其实是栈中的数组里面的值,那当然就可以修改了嘛
我翻看了csdn的文章说
char a[10];
a[0]="hello"这样是错误的
这不是废话吗,char a[10]存储的是char类型,一个字节,而"hello"是地址,占4个字节,能存吗?
这样不就行了
# include<stdio.h>
int main ()
{
const char* a[10];
a[0] = "dwa";
printf("%p", a[0]);
}
c语言没有字符串类型,这句话应该是对的,java,c#都是c实现的,如果那些语言有字符串类型,那也是假的,无非是把常量区的字符串复制到了其他缓冲区里面