指针变量和数组

声明和访问数组:

int arr[2] = {0, 1};
int arr[] = {0, 1};

int i = arr[0];
arr[1] = 23;

C中没有字符串类型,取而代之的是以'\0'结尾的字符数组:

char * str = "abc";    //字符内容存储在堆上
char str1[] = {'a',  'b',  'c',  '\0'};    //字符内容存储在栈上

第一种情况:字符内容会存储在堆上,并在栈里存储str指针变量,变量值为字符在堆上的首地址。
第二种情况:字符内容会存储在栈上,但是不会有额外变量存储字符在堆上的地址,这个地址编译器知道,只会出现在指令中,但并不会作为数据存储。

解释下第二点,总结起来一句话:只有声明指针变量才会将地址作为数据存储在内存。
如我们声明一个整型变量:int i = 15;。这会在堆栈开辟一块空间(4个字节),存储变量的值(15),但是这个15位于堆栈的内存地址却不会作为数据存储,那么我们是怎么访问到这个变量的呢:因为变量在堆栈的地址会出现在指令中,并不是从内存里取的,而仅仅是在指令中的,具体看代码:

int i = 15;
i = 25;

对应汇编为:

movl  $15, -4(%rbp)
movl  $25, -4(%rbp)
#寄存器rbp存储着刚进入子程序时的堆栈地址,对堆栈变量的访问都是用rbp的值加上偏移量(常数)来进行的。

所以采用指针变量操作数据比用非指针变量或数组名要慢,前者需要至少两条汇编指令,后者只需要一条。

数组名和指针变量:

int arr[2] = {0, 1};
int *p = arr;  //等效于 int *p = &arr[0];

//以下是等效操作:
int t;
t = *arr
t = *(arr+0)
t = arr[0]
t = *p
t = *(p+0)
t = p[0]

数组名和指针变量的不同点

p++   //指针变量会变化,等同于:p = &p[1]
arr++ //编译器会报错

arr++之所以会报错,是因为arr的值只会出现在指令中(表现为寄存器rbp的值加偏移量常数),并没存储在内存里,所以无法改变。

猜你喜欢

转载自blog.csdn.net/xuejianbest/article/details/80608021
今日推荐