4、C语言面试笔试--内存操作-指针
文章目錄
- 1、指針變量
- 1.1 基本概念
- 1.2 指針運算
- 1.3 面試題
- 2、 常量和常量指針
- 2.1 字面常量和符號常量
- 2.2 const指針常量
- 2.2.1 常量指針
- 2.2.2 常量指針變量
- 2.2.3 指針常量
- 3、總結
- 1、多級指針
- 2、void * 的含義與void **
- 面試 1
- 面試2
- 面試3
1、指針變量
1.1 基本概念
與普通變量不同,指針定義時的數據類型并不是指針變量本身的數據類型,而是其所指目標數據的數據類型,稱之為基類型。指針初始化的一般形式如下:
數據類型 * 指針名=初始地址值;其中指針變量名前的僅僅是一個說明符,表示其后的名稱是一個指針變量名。這里的并沒有訪問指針目標的含義。
有關指針的注意事項如下:
在定義指針變量后系統為該指針變量分配一個地址大小的存儲單元,指針變量中存放的是地址值。特別注意,無論指針變量的基類型是何種數據類型,占用的內存大小都是相同的,例如“char *p1;double *p2”,在32位系統中有sizeof(p1)=sizeof(p2)=4,即p1和p2兩個指針變量均占用4個字節。
盡管任何指針變量中存放的都是地址值,但一個指針變量只能存放相同基類型的數據地址。
一個指針變量本身占用的空間很小,但可以指向一整塊很大的連續控件,這個一整塊的連續控件通常是采用動態分配函數malloc分配,存放在堆空間中。
指針和地址有什么區別?指針意味著已經有一個指針變量存在,其值是一個地址,指針變量本身也有地址,而地址本身并不代表任何變量存在,地址僅表示內存空間的一個位置。
1.2 指針運算
指針與整數的加減:p±n 以該地址量為基點的其阿芳或后方的第n個數據的地址。例如,對于基類型為type的指針p,p±n的結果是地址值p±n*sizeof(type),其中sizeof(type)稱之為步長,顯然步長是與指針變量的基類型有關。
指針++和–:++代表運算后指向下一個數據的位置,指針–代表運算后指向上一個數據的位置,運算后指針地址值的變化量取決于滋鎮的基類型。
兩個指針相減:并非他們的兩個地址值直接做減法運算,而是兩指針所指地址之間的數據個數。
NULL(與0等效):一旦某個指針賦值為NULL,就將該指針值設置為0,表示真真變量沒有意義,就不能再存儲數據,如int *p=NULL, *p=10,是錯誤的。
野指針:一個指針變量的值(地址值)為垃圾值的指針變量稱之為野指針;
產生野指針的原因及其解決辦法如下:
指針變量定義時沒有被初始化,解決辦法是在定義指針時初始化,可以是具體的地址值,也可以是NULL。
指針p被free或者delete之后沒有置為NULL,后面又去使用。解決辦法就是釋放指針指向的內存空間,然后將指針指向NULL。
指針操作超越了所指變量的作用域,解決辦法是在所指變量的作用域結束之前釋放掉變量的紙質空間,并讓指針指向NULL。
1.3 面試題
以下程序的輸出是()
int *pint=0; pint+=6; printf("%d\n",pint);答案:24
首先題中在定義指針的時候p=0,也就是相當于p=NULL.
其次,+6,其實也就是相當于+6*sizeof(pint);所以輸出的地址值是24
以下程序的輸出結果是什么?
輸出結果是2
解析:8/4=2
以下程序執行會輸出什么?
#include<stdio.h> int main() {char *p="Linux";printf("[%c]",*p++);printf("[%c]",*p);return 0;} 請問執行Test函數會有什么樣的結果? #include<stdio.h> #include <malloc.h> #include <string.h>void test (void) {char *str=(char*)malloc(100);strcpy(str,"hello");free(str);if(str!=NULL){strcpy(str,"world");printf(str);} }void main() {test();}因為執行free(str)語句后,str會成為野指針,其中地址值是不為NULL的垃圾地址,將world字符串存放在垃圾地址空間中,后果難以預料,非常危險。
2、 常量和常量指針
2.1 字面常量和符號常量
常量分為字面常量和符號常量。字面常量只能引用不能修改,字面常量通常保存在靜態數據區,由p指針指向它,不能通過p指針修改該常量。
char *p="abc";像上面這種寫法,在C語言中是在太多了,只能由p指針指向它,不能通過p指針修改該常量。
其中“abc”為常量,程序員最好采用const char *p="abc"定義。這樣在后面執行 *p='x’就會發生錯誤,也能一眼找到原因。
另外,如果p指向的常量字符串不是通過malloc函數分配的,執行free§,會導致程序崩潰。
使用const定義,const的意思是“一個不能被改變的變量”
注意對于define只是替換語句,不是指令,所以沒有;分號,但是,const是指令,所以有;分號。
const常量有數據類型,而宏常量沒有數據類型。
可以把const常量的地址賦給指針變量,例如:const int i=10;int *p=&i ;
C中默認這種隱式轉換,但是在C++中,“cannot convert from ‘const int *’ to ‘int *’”編譯錯誤,需要采用強制轉換,即 int *p=(int *)&i ;
2.2 const指針常量
3類:常量指針、常量指針變量、指針變量
2.2.1 常量指針
在定義指針時用const關鍵字進行修飾,稱為const指針常量。
const char *p用const修飾 * 時稱為常量指針,這樣就不能通過該指針變量修改指向的內容。
2.2.2 常量指針變量
在C++中還可以用const修飾指針變量名,稱之為常量指針變量。
char *const p;
表示指針p是一個常量指針變量,p的值不能再法神改變,所以必須初始化,一旦初始化,p不能指向其他數據,但可以通過指針p修改所指的內容。
解釋:也就是常量指針變量是在指針的前面加上const,這樣,這個指針變量其實也就是初始值代表的指針變量,所以更改這個指針變量的內容,也會導致賦予的指針變量的內容改變。
2.2.3 指針常量
指針變量即為常量指針,又是常量指針變量,例如:
const char * const p;指針常量,前一個const修飾指針變量的定義,后一個const修飾變量名,指針p必須初始化,并且p的值和指向的內容都不能修改。
#include<stdio.h> #include <malloc.h> #include <string.h> int main() {int a=10; int *p=&a; const int * const q=p; *q=56;printf("shuchu %d",*p); printf("chuchu %d",*q); }如上圖,編譯錯誤
3、總結
注意,
const int *p=&a; int const *p=&a;以上這兩個表達式是相同的,都是常量指針,兩個const 都是針對*p。
所以值不能改變,而指向地址可以改變。
而
const是去修飾 p指針的,所以指針地址不能改變,但是指向的內容值是可以改變的,故稱之為常量指針變量。
最后一種
是同時針對地址和值,所以都不能改變。
1、多級指針
在C中指針還可以指向另外的指針,這種指向指針的指針就稱之為多級指針。(這一點,只要理解了,指針變量存儲了指向的地址,另外指針變量自身也有自己的地址)
int x=10; int *p=&x; int **pp=&p; int ***ppp=&pp; //三級指針理解:也就是說,**p取p的地址,(注意不是,p指向的地址,如果寫成p,那就成了p的指向地址了,所以需要寫成 **pp=&p)
2、void * 的含義與void **
void *p; int *p; p1=p2;"無類型”可以包含“有類型”,void *可以指向任何類型的數據。
void ** 可以看做 (void * *)
也就是類型void * 的類型轉換。
(void *) 相當于一個轉換成一個無類型的地址。
(void **)p 相當于(int *) (void *p)
也就是說,( void ** )p相當于轉換成空指針類型,再強制類型轉成p的基類型。
面試 1
int main() {char * p="hello ,world";return 0; }上面程序中p和“hello,world”分別存儲在內存中的哪個區域?
p指針變量是在棧控件分配的,
它指向的常量字符串“hello,world”是在靜態數據區分配的。
面試2
以下程序有什么問題?
#include<stdio.h> #include <malloc.h> #include <string.h> void main() {int i,*p;p=(int *)malloc(3*sizeof(int));for(i=0;i<3;i++){*(p+i)=i+1;printf("%d\n",*(p+i));} p++;free(p); }由于釋放程序的時候,free釋放的不是分配時候的起始地址,所以會導致程序崩潰。
把p++注釋掉即可
面試3
以下程序有什么問題
#include <stdio.h> #include <malloc.h> void main() {int i,*p,**pp=&p;p=(int *)malloc(3*sizeof(int));for(i=0;i<3;i++)*(p+i)=i+1;printf("%d\n",**(++pp));free(p);}對于表達式**(++pp),先執行++pp,是增加pp的地址值,此時pp的地址值加1,會指向一個垃圾地址,應該是讓p的地址加1,所以應該是 **++pp
#include <stdio.h> #include <malloc.h>t void main() {int i,*p,**pp=&p;p=(int *)malloc(3*sizeof(int));for(i=0;i<3;i++)*(p+i)=i+1;printf("%d\n",++**pp);free(p);}總結
以上是生活随笔為你收集整理的4、C语言面试笔试--内存操作-指针的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3、C语言面试笔试--控制结构
- 下一篇: 1、C++招聘笔试--C++中的C