當前位置:首頁 » 編程語言 » c語言指針問題

c語言指針問題

發布時間: 2022-08-22 08:47:00

1. c語言指針問題

你好,二者並不等價, 首先我們知道,a[i]是指向一個有20個char元素的char數組 而p是指向指針的指針
我們可以來分析啊 當你 p=a 時, p即a[0] [0] 的地址 此時你*p 即為取出a[0] [0] 的內容即為'a', 而當你 **p 的時候 就出錯了, 這時候你就是在對 『a』 這個字元取地址,這時候就會出現內存異常錯誤,你肯定是不能對97取地址。你可以強制轉換賦值然後自己試一下 即可
p = (char **)a;

2. c語言中的指針問題

指針計算問題
首先分析***(pp+1)
因為pp是一個數組指針,也就是說pp裡面中的每個元素都是一個指針,因此pp+1就是使指針pp指向數組中的下一下元素的地址,也就是&pp[1]的地址,那麼後面的就好計算了***(pp+1)=***(&pp[1])=**pp[1]=*pp[1][0]=pp[1][0][0]很明顯,就是二維數組指針第二行行一列的指針指向的第一個元素的值,也就是"mnopqr"字元串中的第一個字母m,注意一行有三個元素,"mnopqr"才是第二行。

**pp[0]的計算
**pp[0]=*pp[0][0]=pp[0][0][0]這很明顯,是第一字元串中的第一個字母,也就是"abc"中的字母a

(*(*(pp+1)+1))[4]的計算
(*(*(pp+1)+1))[4]
=(*(*(&pp[1])+1))[4]
=(*(pp[1]+1))[4]
=(*(&pp[1][0]+1))[4]
=(*(&pp[1][1]))[4]
=(pp[1][1])[4]
=pp[1][1][4]

這就很明顯了,結果是pp[1][1]這個指針指向的第5個元素,指針pp[1][1]指向的是"stuvw",其第5個元素就是w

*(pp[1][2]+2)的計算
*(pp[1][2]+2)
=*(&pp[1][2][0]+2)
=*(&pp[1][2][2])
=pp[1][2][2]
很明顯是pp[1][2]指針指向的第3個元素,pp[1][2]指向的是字元串"xyz",因此第3個元素就是字母z

**(pp+1)的計算
**(pp+1)
=**(&pp[0]+1);
=**(&pp[1])
=*pp[1]
=*(pp[1])
=*(&pp[1][0])
=pp[1][0]
因此輸出的是指針pp[1][0]所指向的字元串

如果你對以上的計算有不理解之處,請去本人文庫下載文章《C++指針與動態分配內存new關鍵字專題》裡面有關於指針和[]下標運算符混全運算的相當詳細的講解,文章中的計演算法則適合於所有關於指針與[]的混合運算。

3. c語言指針問題

第一,指針類型的變數(以下稱指針變數)是用來保存地址的,指針變數的類型決定了它可以保存哪種類型的變數的地址。char *s說明s可以用來保存一個char類型的變數的地址(char *是s的類型,說明s可以保存一個char類型的變數的地址)。
第二,s是指向c[0]的,即s保存的是c[0]的地址(s的值是c[0]的地址),對於A. printf("%s\n", s);%s說明是輸出一個以'\0'結尾的字元串,字元串的起始地址在s中,而beijing只有7個字元,數組c分配了8個位元組的空間,所以有空間容納自動添加的'\0',所以A正確。
第三,*是用來說明s是指針類型的。

4. C語言中的指針問題

這樣的"xxxx"應該叫做字元串常量,是存儲在常量區域的,所以不應該修改它。
char a[]="don't know"
是定義了一個數組,數組內的數據復制了字元串的內容。
char *a="don't know"
第二種編譯的時候就應該給你警告了,不能用非常量指針指向一個常量,應該是這樣
const char *a="don't know"
所以不能通過指針改變它。

5. 關於C語言中的指針問題

同學你是沒理解指針是什麼意思。
Root = NULL的意思是將Root指向一處空的位置,這時候Root裡面的一切都是空的(沒有開辟內存空間),當運行到Root->data.value的時候,程序嘗試讀取Root裡面的data元素,這時候就會出現讀取內存越界,因為Root指向的地方是空(沒有分配內存)。

6. C語言指針使用問題

答案沒錯的,是你理解錯了,這里不是要把r替換為s。
重點看這段代碼:
if(*p==ch)
{
*str=*p;
(*str)++;
str++;
}
這里的意思是當p指向的字元和ch相等時,將str所指向的字元變為ch,然後再++對應這里也就是先變為r然後變為s,str++表示str指向下一個字元。這里的str一開始是指向program中的p字元,然後當p指針指向r字元時,str還是指向p字元,接著str將p字元改為r,然後又++改為s。接著p指針繼續向下移動,一直到第二個r,然而此時的str是指向program中的第二個元素也就是r,然後重復和之前一樣的步驟變為s。最後跳出循環後,*str='\0';表示截斷。
哦,還有就是你第一個程序寫錯了,scanf函數要的是指針,不是scanf("%c",char_c);這樣的。char_c是個變數名,應該scanf("%c",&char_c);

That'all

7. c語言指針問題

C語言的大多語法都是簡單易懂的,這常常會給初學者一種「別人都說C語言難,我看也不過如此」的感覺。但是這種感覺常常會停止在初學者學到指針時,這是一些讀者跟我說的。

鑒於很多C語言初學者都覺得指針非常難,

小明定義了一個C語言函數 int f(int * ),為什麼 f(&5) 不能正常工作呢?

如果希望傳遞 5 給函數 f(),在C99中,可以使用下面這種方法:

f( (int[]){5} );
上面這行C語言代碼相當於定義了一個數組,並且數組只有一個元素 5,函數 f() 接收到的參數是該數組,只不過這一過程中的數組名沒有「顯示」。

拋開C99的這個特性,C語言調用 f(&5) 就不能這么寫了,而是需要藉助變數:

int five = 5;
f(&five);
在C語言中,接受某個值指針的函數是有可能通過該指針修改該值的(即使程序員無此打算,C語言還是會一直這么認為),因此只有變數才能勝任。在C語言中,常數是只讀的,只能作為右值,& 運算符是不能處理常數 5 的,f(&five) 會引發編譯錯誤。

f(&five) 會引發編譯錯誤

表達式 * p++ 增加了 p 指向的數值,還是指針 p 本身?

C語言中的 ++ 和 — 運算符的優先順序高於 * 運算符,所以 *p++ 其實就相當於 *(p++)。顯然,++ 運算符增加的是指針 p 本身的值,不過在指針 p 自增之前,*p++會先返回 p 指向的值。如果希望 ++ 運算符增加 p 指向的值,應該使用括弧運算符:(*p)++。

小明想使用指針操作數組里的數值,下面這段C語言代碼有什麼問題?

小明預計程序會輸出 3,但是程序卻輸出了「垃圾值」,他的C語言代碼如下,請看:

int array[5], i, *ip;
for(i = 0; i < 5; i++)
array[i] = i;
ip = array;
printf("%d\n", *(ip + 3 * sizeof(int)));

8. C語言指針問題

1、ptr賦值為arr地址後指向第一個元素,即元素6.
2、*(ptr++) += 123;由於是右側操作(遞增後綴),所以先取ptr地址後再遞增ptr,此時取得的地址還是第一個元素地址(遞增後ptr指向第二個元素,也就是7,這是第一次遞增),因此是對6+123=129,並保存原地址,即第一個元素地址,因此6被改為129。
3、輸出時,由於printf為了左對齊參數格式,必須從右到左處理參數入棧,由於++ptr為左側操作,因此先遞增ptr,ptr指向第三個元素,這是第二次遞增,然後取值,那麼顯然讀取的數據為8、入棧,然後再處理左側參數*ptr,此時ptr沒有遞增還是指向8,因此取得的還是8,入棧。因此輸出都是8

PS:進入函數後,先退棧取值得到第一個參數,也就是後入棧的函數左側參數,輸出,再退棧取得第二個參數,也就是先入棧的函數右側參數,輸出。

這類前後++--的題實際很簡單,先搞清楚優先順序就行了,也就是搞清楚執行先後,左側++--優先順序最高,比如 a*++b--這樣的表達式,不用看肯定是++優先,先處理++b再與a相乘,還比如a+++b,表達式解析時是從左到右,所以先判斷為a的右側操作,所以先取值後遞增,取值後再與b相加。
其二,遞增遞減操作在變數左側的會立刻影響當前取值,因為它是先運算再取值,而在右側操作的會影響後續代碼的變數取值,但不改變當前對變數的取值,因為在遞增遞減前當前取值已經完成。

9. c語言 指針問題

指針的聲明與初始化
1、不恰當的指針聲明
考慮如下的聲明:
int* ptr1, ptr2; // ptr1為指針,ptr2為整數

正確的寫法如下:
int* ptr1, *ptr2;

用類型定義代替宏定義是一個好的習慣,類型定義允許編譯器檢查作用域規則,而宏定義不一定會。
使用宏定義輔助聲明變數,如下所示:
#define PINT int*
PINT ptr1, ptr2;

不過結果和前面所說的一致,更好的方法是使用下面的類型定義:
typedef int* PINT;
PINT ptr1, ptr2;

2、使用指針未初始化
在使用指針之前未初始化會導致運行時錯誤,如下面的代碼:
int* p;
...
printf("%d\n", *p);

指針p未被初始化,可能含有垃圾數據
3、處理未初始化指針
總是用NULL來初始化指針
用assert函數
用第三方工具
把指針初始化為NULL更容易檢查是否使用正確,即便這樣,檢查空值也比較麻煩,如下所示:
int *pi = NULL;
...
if(pi == NULL) {
//不應該解引pi
} else {
//可以使用pi
}

我們可以使用assert函數來測試指針是否為空值:
assert(pi != NULL);

指針的使用問題
緩沖區溢出
緩沖區溢出是指當計算機向緩沖區內填充數據位數時超過了緩沖區本身的容量,使得溢出的數據覆蓋在合法數據上,理想的情況是程序檢查數據長度並不允許輸入超過緩沖區長度的字元,但是絕大多數程序都會假設數據長度總是與所分配的儲存空間相匹配,這就為緩沖區溢出埋下隱患。操作系統所使用的緩沖區又被稱為」堆棧」.。在各個操作進程之間,指令會被臨時儲存在」堆棧」當中,」堆棧」也會出現緩沖區溢出。
下面幾種情況可能導致緩沖區的溢出:
訪問數組元素時沒有檢查索引值
對數組指針做指針算術運算時不夠小心
用gets這樣的函數從標准輸入讀取字元串
誤用strcpy和strcat這樣的函數
1、測試NULL
使用malloc這樣的函數的時候一定要檢查返回值,否則可能會導致程序的非正常終止,下面是一般的方法:
float *vector = malloc(20 * sizeof(float));
if(vector == NULL) {
//malloc分配內存失敗
} else {
//處理vector
}

2、錯誤使用解引操作
聲明和初始化指針的常用方法如下:
int num;
int *pi = #

下面是一種看似等價但是錯誤的聲明方法:
int num;
int *pi;
*pi = #

3、迷途指針
參見《C迷途指針》
4、越過數組邊界訪問內存
沒有什麼可以阻止程序訪問為數組分配的空間以外的內存,下面的例子中,我們聲明並初始化了三個數組來說明這種行為:
#include<stdio.h>
int main()
{
char firstName[8] = "1234567";
char middleName[8] = "1234567";
char lastName[8] = "1234567";
middleName[-2] = 'X';
middleName[0] = 'X';
middleName[10] = 'X';
printf("%p %s\n", firstName, firstName);
printf("%p %s\n", middleName, middleName);
printf("%p %s\n", lastName, lastName);
return 0;
}

熱點內容
蘋果7怎麼給支付寶加密碼 發布:2024-05-04 16:13:12 瀏覽:404
sql培訓視頻 發布:2024-05-04 16:00:59 瀏覽:262
極無雙平新伺服器什麼時候出 發布:2024-05-04 15:50:47 瀏覽:660
c語言千分數 發布:2024-05-04 15:46:31 瀏覽:344
資料庫no 發布:2024-05-04 15:38:00 瀏覽:220
ionic編譯android 發布:2024-05-04 15:20:45 瀏覽:488
雲伺服器在哪買 發布:2024-05-04 15:19:18 瀏覽:85
華為如何用電腦解鎖手機密碼 發布:2024-05-04 14:54:38 瀏覽:574
斐波那契數列的遞歸演算法 發布:2024-05-04 14:34:55 瀏覽:969
數字支付密碼哪裡找 發布:2024-05-04 14:26:50 瀏覽:86