1、字符數組?
1、什麼是字符數組?
一個數組中全部成員都是字符來的。
例子:char A[5]
;
2、字符數組賦值?
1)定義同時初始化?
char A[10] = {'h','e','l','l','o'}
; -> 剩餘沒有賦值的5個元素都爲0
char A[10] = {"hello"}
; -> 將字符串hello賦值給數組
char A[10] = {"10086"}
; -> char A[10]已經決定每一個成員都是字符類型,所以 ‘1’,‘0’,‘0’,‘8’,‘6’
int A[10] = {1,0,0,8,6}
; -> int A[10]已經決定每一個成員都是整型類型,所以 1,0,0,8,6
char A[10] = "hello"
; -> {}可以省略!
3、將字符串常量賦值給數組在內存中是如何變化?
int a = 10;
char A[10] = "hello";
其實將常量區中的值賦值給棧區空間。
1)注意:
所有字符串常量在常量區存在都會以'\0'
作爲結束的標誌。
Oct Dec Hex Char
000 0 00 NULL '\0'
2)例如:
hello\0world\0apple\0tree\0
2 、字符指針?
整型指針 -> int類型
字符指針 -> char類型
例子1:
char a = 'h';
char *p = &a;
->p
就是字符指針 -> 指向一個字符類型的數據a
例子2:
char *p = "hello";
-> 正確!
究竟p
指向字符?還是指向一個字符串?
字符指針p
永遠只能指向字符,不可能指向整個字符串,在這個例子,p指向"hello"這個字符串的首元素'h'
的地址
注意:
1)p
是一個指針變量,所以只能存放地址,存放着是hello中’h’的地址。
2)p
是一個指針變量,不能存放字符串,不是將常量區的hello拷貝過來。
3)字符指針只能指向字符,不能指向字符串。
4)%s
輸出字符串
輸出原則:給定一個地址,判斷地址上值是不是'\0'
。
如果不是\0
,則打印該地址上的值並將該地址往後挪動一個單位。
如果是\0
,就停止打印。
請問以下代碼是什麼含義?
char A[10] = "hello";
char *p = "hello";
printf("A = %s\n",A); //A是字符串首元素的地址,結果:hello -> 打印的是棧區的hello
printf("p = %s\n",p); //p是字符串首元素的地址,結果:hello -> 打印的是常量區的hello
結論:
1)只要將一個字符串賦值給一個字符數組,那麼就會把常量區的字符串拷貝到該字符數組中。
2)只要將一個字符串賦值給一個字符指針,那麼該指針就是存放着這個字符串的首元素的地址。
#include <stdio.h>
int main(int argc,char *argv[])
{
char A[] = "helloworld";
char *p = "helloworld";
char *pa = A; //pa等價於數組名A,使用pa來訪問東西,都是屬於棧區!
printf("sizeof(A) = %d\n",sizeof(A));//11
printf("sizeof(p) = %d\n",sizeof(p));//4
printf("A = %s\n",A); //helloworld
printf("*A = %c\n",*A); //h 棧區
printf("*(A+1) = %c\n",*(A+1)); //e 棧區
printf("A+1 = %s\n",A+1); //elloworld 棧區
printf("p = %s\n",p); //helloworld 常量區
printf("pa = %s\n",pa); //helloworld 棧區
printf("A[0] = %c\n",A[0]); //h 棧區
A[0] = 'k';
printf("A = %s\n",A); //kelloworld 棧區
printf("*p = %c\n",*p); //h 常量區
//*p = 'k'; //26行段錯誤,原因常量區不能修改值。
//printf("p = %s\n",p);
printf("*pa = %c\n",*pa); //k 棧區
pa[0] = 'm';
printf("pa = %s\n",pa); //melloworld
return 0;
}
14、有以下程序
main()
{
char s[]=“Yes\n/No”,*ps=s;
puts(ps+4);
*(ps+4)=0;
puts(s);
}
程序運行後的輸出結果是( B )
A) n/No B) /No C) n/No D) /No
Yes Yes Yes /No
/No /No Yes
16、有以下程序
main()
{
char s[]= “ABCD”,*p;
for(p=s+1;p<s+4;p++)
printf(“%s\n”,p);
}
程序運行後的輸出結果是()
BCD
CD
D
17、以下程序運行後的輸出結果是( gae )
main()
{
char a[]=“Language”,b[]=“Programe”;
char *p1,*p2;
int k;
p1=a;p2=b;
for(k=0;k<8;k++)
if(*(p1+k)==*(p2+k)) 等價於 if(p1[k] == p2[k])
printf(“%c”,*(p1+k));
}
3、指針數組
1、什麼是數組指針?什麼是指針數組?
數組指針是一個指針來的,這個指針指向整一個數組。
指針數組是一個數組來的,這個數組的每一個成員都是指針。
2、如何定義指針數組?
定義的方法與定義普通數組一致。
1)給一個數組名 p
2)確定元素的個數,使用[]括號括住它 p[5]
3)確定每一個元素的類型 int *pa
4)將第3步的變量名去掉 int*
5)將第4步的結果寫在第2步結果的前面 int* p[5] -> 指針數組
3、如何定義數組指針?
int A[5];
int (*p)[5]; = &A; --> 數組指針
練習: 提示: strlen()計算字符串實際長度
15、有以下程序
main()
{
char str[][20]={“Hello”,”Beijing”},*p=str[0];
printf(“%d\n”,strlen(p+20));
}
程序運行後的輸出結果是( C )
A) 0 B) 5 C) 7 D) 20
18、有以下程序
main()
{
char *p[10]={“abc”, “aabdfg”, “dcdbe”, “abbd”, “cd”};
printf(“%d\n”,strlen(p[4]));
}
執行後輸出結果是( A )
A) 2 B) 3 C) 4 D) 5
19、若有定義:int *p[3];,則以下敘述中正確的是( B )
A)定義了一個基類型爲int的指針變量p,該變量具有3個指針。
B)定義了一個指針數組p,該數組含有3個元素,每個元素都是基類型爲int的指針。
C)定義了一個名爲*p的整型數組,該數組含有3個int類型元素。
D)定義了一個可指向一維數組的指針變量p,所指一維數組應具有3個int類型元素。
若有以下程序:
void main()
{
char *a[3] = {"I","love","China"};
char **ptr = a;
printf("%c %s",*(*(a+1)+1),*(ptr+1)); // 'o' "love"
}
4、const指針?
1、什麼是const指針?
已經學習了非常多指針種類,例如:整型指針int*、字符指針char* -> 指的是指針的類型
const指針並不是指針的類型,只是用於修飾特定的指針類型。
2、使用場景?
一般const作用形式參數。
例子:
int fun(int a); //a=10 -> 可以隨時通過a修改a本身的值。
int fun(const int a); //a=10 一旦a被初始化後,不能通過a修改a的值。
int main()
{
fun(10);
}
結論: const修改了某個變量之後,就不能通過該變量修改該變量裏面的值。
3、 例子:
#include <stdio.h>
int main()
{
/* const作用於整型變量
const int a;//使用const修飾變量a,一旦變量初始化隨機值之後,就不能通過a修改a的值
a = 100; //編譯出錯: error: assignment of read-only variable ‘a’
printf("a = %d\n",a);
//a = 200; //編譯出錯: error: assignment of read-only variable ‘a’
//printf("a = %d\n",a);
*/
/* const作用於指針變量本身
int a = 100;
int b = 50;
int * const p = &a; //const修飾p的本身,所以一旦p被初始化之後,就不能通過p修改p的本身
//p = &b; //編譯出錯:error: assignment of read-only variable ‘p’
*p = 200; //正確的,因爲const修飾p的本身,但是沒有修飾p指向的內容,所以可以通過p修改p指向的內容
printf("a = %d\n",a);
*/
/* const修飾指針變量指向的內容
int a = 100;
int b = 50;
const int *p = &a; //const修飾p指向的內容,而不是修飾p
p = &b; //可以通過p修改p本身。
//*p = 200; //編譯出錯:error: assignment of read-only location ‘*p’
//不可以通過p修改p指向的內容。
b = 200; //可以,沒有通過p修改p指向的內容
*/
return 0;
}
4、結論
int * const p
; -> const
修飾p
的本身,一旦p
被賦值了某個一個地址之後,就不能通過p
修改p
的地址。
int * const p = xxxx地址(正確) p = yyyy地址(錯誤)
-> 但是可以通過p修改p指向的內容。
*p 隨便搞
const int *p; 等價 int const *p;
-> const修飾p指向的內容,p隨意指向任何的地址
const int *p = xxxx地址(正確) p = yyyy地址(正確)
*p 出現錯誤